Guzzle Pool: как дождаться завершения всех запросов без тайм-аута?

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

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

cURL error 18: transfer closed with outstanding read data remaining

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

Интересно то, что если я сделаю запрос через Postman (например), то мне все равно придется ждать 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 источников.


person Radical_Activity    schedule 03.04.2019    source источник


Ответы (1)


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

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

person Alexey Shokov    schedule 04.04.2019
comment
Спасибо за ответ. Я пробовал это сделать, и больше не получаю никаких ошибок (отклонений), однако в данных ответа я получаю «null». Почему могло случиться так, что он неплохо работает с таким программным обеспечением, как PostMan, но не работает с Guzzle? - person Radical_Activity; 05.04.2019