What is exactly “concurrency” in Guzzle?

大憨熊 提交于 2019-12-10 19:07:01

问题


I have not found much information about concurrency option in Pool.

If this is a number of TCP sockets which could be opened on server, then the question is "What number of concurrency could I use in order to handle requests quicker?".

I have this example of using 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();

It took about 10 seconds to go over ~20 sites with concurrency set to 5. Now I'm thinking like, "Okay, this is number of sockets. Sockets ~ Ports. I have 65535 ports. Cool, why not set concurrency 50 and I should get all results in a second or so?". Nice, I set it to 50 and... it took 8 seconds. However an hour ago the results were like 18 seconds vs 24 (for 50 concurrency, so it's even slower).

So the question is:

  1. How to determine which concurrency I could use in order to optimize the proccess and make it faster as it possible to do?
  2. What is concurrency anyway?

回答1:


It's what you'd expect it to be. You send X concurrent requests but only concurrency requests are sent at the same time. Whenever a request finishes then another one is queued (source code)

Here's how this is done in source:

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());
}    

This method is called every time a request finishes (function step is set to be called after every success of failiure callback).

However as a general rule more does not always mean better because you might hit other limits elsewhere like OS sockets or ISP rate limiting or remote server rate limiting (if all requests go to the same server). In most cases the optimal value is found via trial and error.



来源:https://stackoverflow.com/questions/46452555/what-is-exactly-concurrency-in-guzzle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!