Guzzle Pool: как дождаться завершения всех запросов без истечения времени ожидания? - PullRequest
0 голосов
/ 03 апреля 2019

Я использовал Guzzle Pool для запроса данных (около 1-2 МБ на каждый запрос) с внешнего сервера за последние 6 месяцев. Я делаю 5 одновременных запросов. Однако все изменилось, и внешний сервер, похоже, перегружен и поэтому стал очень медленным. Иногда это очень быстро, например, 1-2 секунды, но часто серверу приходится ждать 2+ минуты на каждый запрос.

Это не должно быть проблемой, хотя. Однако в настоящее время (поскольку выполнение запросов становится медленным), некоторые из моих запросов в пуле возвращают ошибку:

cURL error 18: transfer closed with outstanding read data remaining

Обычно это происходит после ожидания ровно 2 минут.

Интересно то, что если я сделаю запрос через Почтальона (например), мне все равно придется подождать 2-3 + минуты, но в итоге я получил ответ.

Так что это заставило меня поверить, что Guzzle блокирует запросы через 2 минуты. Однако я не смог найти никаких настроек, чтобы изменить это. Я даже пытался отправить заголовки Keep Alive и Content-Length, но они не работали (возможно, я их не правильно использовал).

Вот часть моего текущего кода, который выполняет запросы Guzzle Pool. (Я использую PHP 7.1, Guzzle 6.3 и Laravel 5.7).

$headers = ['Authorization' => 'Bearer ' . $token];

$client  = new Client();

$requests = function ($urls, $headers)
{
    foreach ($urls as $key => $url)
    {
        yield new Requests('GET', $url, $headers);
    }
};

$pool = new Pool($client, $requests($urls, $headers),
[
    'concurrency' => 5,
    'fulfilled'   => function ($response, $index)
    {
        echo 'fulfilled -> ' . $index;
    },
    'rejected' => function ($reason, $index)
    {
        echo 'rejected -> ' . $index . ' -> error:' . $reason->getMessage();
    },
]);

$promise = $pool->promise();
$promise->wait();

К сожалению, я не могу поделиться URL-адресом внешнего сервера, потому что он приватный.

Что я здесь не так делаю, что не позволяет запросу дождаться его завершения / отправки по данным?


Обновление: Я попробовал рекомендацию @Alexey Shokov, которая избавляла от отклоненных состояний. Запросы не истекают через 2 минуты. Однако я получаю нулевое значение в ответ, как только получаю что-то из этих ранее timed out источников.

1 Ответ

1 голос
/ 04 апреля 2019

Похоже, что существует проблема на стороне сервера. Ошибка указала, что клиент cURL видит несоответствие между ожидаемым размером ответа и реальным размером ответа, отправленного сервером.

Взгляните на эту ТАКУЮ тему , та же проблема. Я думаю, что стоит попытаться установить версию HTTP на 1.0, как указано в обсуждении с опцией version Guzzle или непосредственно в объекте Request (yield new Requests('GET', $url, $headers, null, '1.0')).

...