将请求增量添加到Guzzle 5.0池(滚动请求)

时间:2015-01-23 07:37:53

标签: php curl iterator guzzle

我使用Guzzle使用pool并行(或异步)获取大量网址:

$client = new GuzzleHttp\Client([
    'base_url' => 'http://httpbin.org',
]);

$requests = [];

for ($i = 0; $i < 8; ++$i) {
    $requests[] = $client->createRequest('GET', '/get');
}

$pool = new GuzzleHttp\Pool($client, $requests, [
    'pool_size' => 4,
    'complete' => function (GuzzleHttp\Event\CompleteEvent $event) {
        var_dump($event->getRequest()->getUrl());
    },
]);

$pool->wait();

var_dump(count($requests));

如果我在控制台中运行上面的内容,它会显示预期的输出:

string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
int(8)

现在,我希望能够根据某些条件向同一个池添加其他请求,我相信这种行为通常称为滚动[并行]请求,但在阅读并重新启动后 - 阅读我无法解决的文档。这是我尝试过的东西:

$client = new GuzzleHttp\Client([
    'base_url' => 'http://httpbin.org',
]);

$requests = [];

for ($i = 0; $i < 8; ++$i) {
    $requests[] = $client->createRequest('GET', '/get');
}

$i = 0;
$pool = new GuzzleHttp\Pool($client, $requests, [
    'pool_size' => 4,
    'complete' => function (GuzzleHttp\Event\CompleteEvent $event) use (&$i, $client, &$requests) {
        var_dump($event->getRequest()->getUrl());

        if (++$i % 3 == 0) {
            $requests[] = $client->createRequest('GET', '/ip');
        }
    },
]);

$pool->wait();

var_dump(count($requests));

/get的每三个请求都应该向/ip添加一个新请求,$requests数组实际上正在增长(到10个元素,而不是预期的11个),但请求是从未真正执行过。有没有办法让Guzzle池执行初始化后的请求?

1 个答案:

答案 0 :(得分:3)

有可能,请参阅我在guzzle issue Suggestions to GuzzleHttp\Pool #946上的评论获取完整示例或这个要点,以获得generator, retry and sequential send with guzzle之间比较的更深入的示例。

关于您的示例,请参阅我的内联评论:

$client = new GuzzleHttp\Client([
    'base_url' => 'http://httpbin.org',
]);

$requests = [];

for ($i = 0; $i < 8; ++$i) {
    $requests[] = $client->createRequest('GET', '/get');
}

$generator = new ArrayIterator($requests); // use an iterator instead of an array

$i = 0;
$pool = new GuzzleHttp\Pool($client, $generator, [ // use the iterator in the pool
    'pool_size' => 4,
    'complete' => function (GuzzleHttp\Event\CompleteEvent $event) use (&$i, $client, &$generator) {
        var_dump($event->getRequest()->getUrl());

        if (++$i % 3 == 0) {
            $generator->append($client->createRequest('GET', '/ip')); // append new requests on the fly
        }
    },
]);

$pool->wait();

这会产生您的预期输出:

string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(22) "http://httpbin.org/get"
string(21) "http://httpbin.org/ip"
string(21) "http://httpbin.org/ip"
string(21) "http://httpbin.org/ip"

请注意,请求最后会附加 。这与AbstractRetryableEvent::retry的工作方式相反,后者将在当前队列之间的某处挤压重试,而不是在最后附加它。