狂饮池:如何在不超时的情况下等待所有请求完成?

时间:2019-04-03 13:21:14

标签: php curl guzzle guzzlehttp

在过去6个月中,我一直在使用Guzzle Pool向外部服务器请求数据(每个请求大约1-2 MB)。我一次要同时执行5个请求。但是,情况发生了变化,外部服务器似乎过载,因此变得非常慢。有时速度非常快,例如1-2秒,但是很多时候服务器需要为每个请求等待2分钟以上。

这应该不是问题。但是如今(由于发出请求的速度变慢),我在池中的某些请求返回了错误:

cURL error 18: transfer closed with outstanding read data remaining

通常在等了2分钟后执行此操作。

但是有趣的是,如果我通过邮递员(例如)发出请求,那么我仍然必须等待2-3分钟以上,但最终还是得到了响应。

因此,这使我相信Guzzle在2分钟后阻止了请求。但是,我找不到任何设置来更改此设置。我什至尝试发送Keep AliveContent-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来源那里得到了一些回馈,我就会得到null作为响应。

1 个答案:

答案 0 :(得分:1)

服务器端似乎有问题。该错误表明cURL客户端看到服务器发送的预期响应大小与实际响应大小不匹配。

看看this SO topic,同样的问题。我认为值得尝试像使用Guzzle's version option或直接在Request对象(yield new Requests('GET', $url, $headers, null, '1.0'))中讨论的那样将HTTP版本设置为1.0。