如何处理GuzzleHTTP异步请求而不会阻塞?

时间:2018-07-05 12:01:42

标签: php asynchronous guzzle

我需要编写一个处理器,该处理器可以潜在地向外部服务发送许多HTTP请求。因为我想最大化性能,所以我希望最小化阻塞。我正在使用PHP 5.6和GuzzleHTTP。

GuzzleHTTP确实有一个用于异步请求的选项。但是由于在PHP中确实只有1个线程可用,所以我需要分配一些时间来处理它们。不幸的是,我只看到一种实现方法-调用plt.legend() ,该方法会阻塞直到所有请求都被处理。那不是我想要的。

相反,我希望有一些方法可以处理到达的所有内容,然后返回。这样我就可以按照以下方式做一些事情:

wait

这可能吗?

1 个答案:

答案 0 :(得分:0)

好吧...自己弄清楚了

$handler = new \GuzzleHttp\Handler\CurlMultiHandler();
$client = new \GuzzleHttp\Client(['handler' => $handler]);
$promise1 = $client->getAsync("http://www.stackoverflow.com");
$promise2 = $client->getAsync("http://localhost/");

$doneCount = 0;

$promise1->then(function() use(&$doneCount) {
    $doneCount++;
    echo 'Promise 1 done!';
});
$promise2->then(function() use(&$doneCount) {
    $doneCount++;
    echo 'Promise 2 done!';
});

$last = microtime(true);
while ( $doneCount < 2 ) {
    $now = microtime(true);
    $delta = round(($now-$last)*1000);
    echo "tick($delta) ";
    $last = $now;

    $handler->tick();
}

我得到的输出是:

  

刻度(0)刻度(6)刻度(1)刻度(0)刻度(1001)刻度(10)刻度(96)承诺2完成!刻度(97)承诺1完成!

魔术成分是创建CurlMultiHandler您自己,然后在方便时在其上调用tick()。之后,它会像往常一样承诺。如果队列为空,则tick()立即返回。

请注意,如果没有活动,它仍可以阻止最多1秒钟(默认)。如果需要,也可以更改它:

$handler = new \GuzzleHttp\Handler\CurlMultiHandler(['select_timeout' => 0.5]);

该值以秒为单位,但带有浮点数。