【问题标题】:Guzzle Pool: how to wait for all requests to finish without timing out?Guzzle Pool:如何等待所有请求完成而不超时?
【发布时间】:2019-04-03 13:21:14
【问题描述】:

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

不过,这应该不是问题。但是现在(因为发出请求变得很慢),我在池中的一些请求正在返回错误:

cURL error 18: transfer closed with outstanding read data remaining

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

有趣的是,如果我通过 Postman(例如)发出请求,我仍然需要等待 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 作为响应。

【问题讨论】:

    标签: php curl guzzle


    【解决方案1】:

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

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

    【讨论】:

    • 感谢您的回答。我已经尝试过这样做,但我不再收到任何错误(拒绝),但是我在响应数据中得到了“null”。为什么它在 PostMan 这样的软件上运行得很好,但在 Guzzle 上却不行?
    猜你喜欢
    • 2017-08-02
    • 2015-04-17
    • 1970-01-01
    • 2020-05-26
    • 2020-01-06
    • 2021-02-16
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    相关资源
    最近更新 更多