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


Incrementally add requests to a Guzzle 5.0 Pool (Rolling Requests)

我正在使用Guzzle使用池并行(或异步)获取大量URL:

$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 池执行初始化后请求?

有可能,请参阅我在 guzzle 问题中的评论 对 GuzzleHttp''Pool #946 的建议 有关完整示例,或此要点以获取更深入的示例,以比较生成器、重试和使用 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 的工作原理相反,它将在当前队列之间的某个位置挤压重试,而不是将其附加到末尾。