Swoole-src: 同步模式下,等待某个协程结束再响应,怎么处理呢?chan只能在协程里用

Created on 10 Jan 2019  ·  13Comments  ·  Source: swoole/swoole-src

question

Most helpful comment

开启协程, 做一个全局的channel, 然后向里面push([$request, $response]), 然后单独开一个协程, pop出来, 逐个处理.

All 13 comments

把全局代码包到协程里使用

在协程内响应

把全局代码包到协程里使用

主要是不想大改原有项目的逻辑,又想使用协程

其实给当前 worker加个标记别接受新的请求就可以了

function onRequest($request, $response) {
    go(function () use (&$request, &$response) {
        // do something...
        $response->end();
    });
}

这样试试呢?
而且包在协程里也无需改逻辑呀

function onRequest($request, $response) {
    go(function () use (&$request, &$response) {
        // do something...
        $response->end();
    });
}

这样试试呢?
而且包在协程里也无需改逻辑呀

原有逻辑里有很多静态变量和静态属性,放协程里,如果协程里有阻塞代码,协程就会挂起,然后新请求时来,静态变量和静态属性就可能会被覆盖

你这种情况, 同步和异步一起使用, 没有意义, 会产生错误

你这种情况, 同步和异步一起使用, 没有意义, 会产生错误

其实就是让 worker 只处理一个请求,这个请求处理完,再接着处理新的请求,这样就不用担心,静态变量被覆盖了。

function onRequest($request, $response) {
     // 这里标记 worker 别接受新请求了

    go(function () use (&$request, &$response) {
        // do something...
        // 这里可以开心地使用协程了
        $response->end();
        // 请求处理完,告诉worker可以接受新请求了
    });

}

这种方式可以让很多老程序使用上协程,感觉可以是半异步半同步了

那为什么要用协程?..

那为什么要用协程?..

function onRequest($request, $response)
{
    // 这里标记 worker 别接受新请求了

    go(function () use (&$request, &$response) {
        // do something...
        //并发请求 n
        $n = 5;
        for ($i = 0; $i < $n; $i++) {
            $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 80);
            $cli->setHeaders([
                'Host'            => "local.ad.oa.com",
                "User-Agent"      => 'Chrome/49.0.2587.3',
                'Accept'          => 'text/html,application/xhtml+xml,application/xml',
                'Accept-Encoding' => 'gzip',
            ]);
            $cli->set(['timeout' => 2]);
            $cli->setDefer();
            $cli->get('/test.php');
            $clients[] = $cli;
        }

        for ($i = 0; $i < $n; $i++) {
            $r        = $clients [$i]->recv();
            $result[] = $clients[$i]->body;
        }
        $response->end(json_encode($data));

        // 请求处理完,告诉worker可以接受新请求了
    });

}

这样就可以使用协程并发处理此类问题,同时也不影响老代码

只要能标记 worker 是否接受新请求的开关,这种想法感觉还是有意义的,至少比全同步好点

开启协程, 做一个全局的channel, 然后向里面push([$request, $response]), 然后单独开一个协程, pop出来, 逐个处理.

开启协程, 做一个全局的channel, 然后向里面push([$request, $response]), 然后单独开一个协程, pop出来, 逐个处理.

感谢,完美解决了

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lotarbo picture lotarbo  ·  4Comments

Gemorroj picture Gemorroj  ·  3Comments

qifengzhang007 picture qifengzhang007  ·  3Comments

AndyChanCode picture AndyChanCode  ·  3Comments

sshymko picture sshymko  ·  3Comments