× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

并发调用

并发请求

在协程版本的Client中,实现了多个客户端并发发包功能(setDefer机制)。

通常,如果一个业务请求中需要做一次redis请求和一次mysql请求,那么网络IO会是这样子:

redis发包->redis收包->mysql发包->mysql收包

以上流程网络IO的时间就等于 redis网络IO时间 + mysql网络IO时间。

而对于协程版本的Client,网络IO可以是这样子:

redis发包->mysql发包->redis收包->mysql收包

以上流程网络IO的时间就接近于 MAX(redis网络IO时间, mysql网络IO时间)

现在支持并发请求的Client有:

  • Swoole\Coroutine\Client
  • Swoole\Coroutine\Redis
  • Swoole\Coroutine\MySQL
  • Swoole\Coroutine\Http\Client

除了Swoole\Coroutine\Client,其他Client都实现了defer特性,用于声明延迟收包。

因为Swoole\Coroutine\Client的发包和收包方法是分开的,所以就不需要实现defer特性了,而其他Client的发包和收包都是在一个方法中,所以需要一个setDefer()方法声明延迟收包,然后通过recv()方法收包。

setDefer 使用实例

function onRequest($request, $response)
{
    //并发请求 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));
}

  • 张文诏

    现在的 最新release 支持协程吗? 还有就是如果不支持 要想实现 MAX(redis网络IO时间, mysql网络IO时间) 这个要怎么办 怎么来处理 所有的异步都 返回后的回调

  • xhc

    请教一个问题,在某些场景下,需要手动挂起协程,在条件满足的情况下,在手动切换回来。 请问以后的版本是否支持此场景?

  • chale

    条件满足怎么判定 一定时间后?

  • ccyy

    请问,setDefer()后recv()的返回值是什么?

  • lingyu

    ,setDefer()后recv()的返回值true或者false

  • 新用户(手机注册)

    new Swoole\Coroutine\Http\Client() 如果http并发请求的是同一个服务,ip port完全一样,这里只有'sock' 一样的recv()返回成功,其他的都返回失败吗?

  • 新用户(手机注册)

    sock 字段是否为链接唯一标记,如果向通一个服务端同时发多次请求,recv是怎么取值的?

  • 新用户(手机注册)

    http并发请求同一个服务端,这里如果执行close close后,下次recv 会不会有bug