什么是"并发"在Guzzle?

时间:2017-09-27 16:09:11

标签: php concurrency guzzle

我在concurrency中找不到有关Pool选项的更多信息。

如果这是可以在服务器上打开的多个TCP套接字,那么问题是"我可以使用多少并发数来更快地处理请求?"。

我有使用Pool

的这个例子
    // I am using Laravel, this is basically retrieving entities from DB
    $exchangers = Exchanger::all();

    $client = new Guzzlelient();

    $requests = [];
    foreach ($exchangers as $exchanger)
    {
        $requests[$exchanger->id] = new Request('GET', $exchanger->xml_feed_url);
    }

    $pool = new Pool($client, $requests, [
        'concurrency' => 5,
        'options' => [
            'verify' => false
        ],
        'fulfilled' => function ($response, $index) {
            echo "fulfilled: " . $index."\n";
        },
        'rejected' => function ($reason, $index) {
            echo "rejected: " . $index. "\n";
        },
    ]);

    // Initiate the transfers and create a promise
    $promise = $pool->promise();

    // Force the pool of requests to complete.
    $promise->wait();

将并发设置为5的大约20个站点花了大约10秒钟。 现在我想,"好的,这是套接字的数量。套接字〜端口。我有65535个端口。很酷,为什么不设置并发50,我应该在一秒左右得到所有结果?"。很好,我把它设置为50并且......花了8秒钟。不过一个小时前,结果就像18秒对24(50并发,所以它甚至更慢)。

所以问题是:

  1. 如何确定我可以使用哪种并发来优化过程并使其尽可能快地进行?
  2. 什么是并发?

1 个答案:

答案 0 :(得分:0)

这是你所期望的。您发送X个并发请求,但同时只发送concurrency个请求。每当请求完成,然后另一个请求排队(source code

以下是在源代码中完成的操作:

private function refillPending()
{
    if (!$this->concurrency) {
        // Add all pending promises.
        while ($this->addPending() && $this->advanceIterator());
        return;
    }
    // Add only up to N pending promises.
    $concurrency = is_callable($this->concurrency)
        ? call_user_func($this->concurrency, count($this->pending))
        : $this->concurrency;
    $concurrency = max($concurrency - count($this->pending), 0);
    // Concurrency may be set to 0 to disallow new promises.
    if (!$concurrency) {
        return;
    }
    // Add the first pending promise.
    $this->addPending();
    // Note this is special handling for concurrency=1 so that we do
    // not advance the iterator after adding the first promise. This
    // helps work around issues with generators that might not have the
    // next value to yield until promise callbacks are called.
    while (--$concurrency
        && $this->advanceIterator()
        && $this->addPending());
}    

每次请求完成时都会调用此方法(函数step设置为在每次成功执行failiure回调后调用)。

然而,作为一般规则,更多并不总是意味着更好,因为您可能会遇到其他限制,如OS套接字或ISP速率限制或远程服务器速率限制(如果所有请求都转到同一服务器)。在大多数情况下,通过反复试验找到最佳值。