controller 的协程休眠测试

我安装了 swoole 扩展和 revolt/event-loop 来测试协程的效果

process.php 里依次对三种情况进行测试:

    'webman' => [
        'handler' => Http::class,
        'listen' => 'http://0.0.0.0:8787',
        'count' => 1,
        'user' => '',
        'group' => '',
        'reusePort' => false,
//        'eventLoop' => "",
        'eventLoop' => \Workerman\Events\Swoole::class,
//        'eventLoop' => \Workerman\Events\Fiber::class,
        'context' => [],
        'constructor' => [
            'requestClass' => Request::class,
            'logger' => Log::channel('default'),
            'appPath' => app_path(),
            'publicPath' => public_path()
        ]
    ],

控制器代码如下:

    public function json(Request $request)
    {
        Timer::sleep(10);
//        usleep(1000*30);
        return json(['code' => 0, 'msg' => "ok",'data'=>$request->cookie()]);
    }

依次快速发出两个请求,发现第2 个请求是在第一个请求结束后才开始处理的,第一个请求耗时 10.x 秒,第二个请求耗时 20 秒。

用协程不是应该两个请求同时被处理吗,怎么三种eventLoop配置的效果都一样?

176 2 1
2个回答

二环狄仁杰

是不是协程并非框架自动,必须要手动创建协程并投递任务:

        Coroutine::create(function () use ($request) {
            Timer::sleep(10);
            var_dump(sprintf("%s-%d","你好协程",time()));
        });

但如果是手动的话,为什么文档里又要求下面这样,按理来说控制器方法内部就不是协程,就不需要使用 Context?

class TestController
{
    public function index(Request $request)
    {
        Context::set('name', $request->get('name'));
        Timer::sleep(5);
        return Context::get('name');
    }
}

是我理解哪里出了问题吗

  • lsmir2 2天前

    是指在协程状态下 全局变量污染 所以 才需要 Context::set Context::get
    文档里的第一个例子写的很清楚 自己测下就晓得了
    将进程数设置为1,当我们连续发起两个请求时
    http://127.0.0.1:8787/test?name=lilei
    http://127.0.0.1:8787/test?name=hanmeimei
    我们期望两个请求返回的结果分别是 lilei 和 hanmeimei,但实际上返回的都是hanmeimei。
    这是因为第二个请求将静态变量$name覆盖了,第一个请求睡眠结束时返回时静态变量$name已经成为hanmeimei

  • qqxxr 2天前

    你改了这些,项目需要重启。执行php start.php status看了,你的进程和event都改过来了吗

类似问题之前回复过,浏览器会默认会复用连接,前一个请求没有返回时,后一个请求会在浏览器排队等待。在浏览器里network里计时能看到排队情况。
为了避免复用连接排队,你可以通过curl来测试,curl http://127.0.0.1:8787/

🔝