使用 Guzzle HTTP PHP 客户端限制连接时间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20847633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 03:36:41  来源:igfitidea点击:

Limit connecting time with Guzzle HTTP PHP client

phpguzzle

提问by user3147578

I'm using Guzzle to open a list of url-s and get the headers. Some of the urls are taking too long to respond and can't be openned and i want to ignore them. It takes me up to 20+ seconds before Guzzle throws an exception and i want to change this and limit the time for connecting to 2 sec. I have this code but it still takes much longer:

我正在使用 Guzzle 打开 url-s 列表并获取标题。一些 url 响应时间太长,无法打开,我想忽略它们。在 Guzzle 引发异常之前,我最多需要 20 多秒,我想更改此设置并将连接时间限制为 2 秒。我有这个代码,但它仍然需要更长的时间:

<?php
include 'vendor/autoload.php';

$start = new \DateTime("now");

$start = $start->format("d.m.Y H:i:s");
echo $start."\n";
$client = new Guzzle\Http\Client();

Guzzle\Http\StaticClient::mount();

try {
    $request = $client->get('http://takestoolongexample', [], ['connect_timeout' => 2, 'timeout' => 3, 'debug' => true]);
    $response = $request->send();

    var_dump($response->getStatusCode());
} catch (Exception $e) {
    echo "\n".$e->getMessage()."\n";
}

$end = new \DateTime("now");

$end = $end->format("d.m.Y H:i:s");

echo "\n".$end."\n";
?>

Here's an example result. As you can see, it took 13 seconds.

这是一个示例结果。如您所见,耗时 13 秒。

$ php test.php
30.12.2013 22:00:07
* getaddrinfo(3) failed for takestoolongexample:80
* Couldn't resolve host 'takestoolongexample'
* Closing connection 0

[curl] 6: Couldn't resolve host 'http://takestoolongexample' http://takestoolongexample

30.12.2013 22:00:20

(http://takestoolongexamplewas a real url, changed it here)

http://takestoolongexample是一个真实的网址,在这里更改了它)

回答by phpisuber01

Here's the updated solution to this problem for Guzzle version (Guzzle 4).

这是 Guzzle 版本 (Guzzle 4) 的此问题的更新解决方案。

$request = $client->get(sprintf("%s/noisesize.api", $this->noiseConfig->url), [
    'timeout' => 5, // Response timeout
    'connect_timeout' => 5, // Connection timeout
]);

Throws Guzzle\Http\Exception\RequestException

投掷 Guzzle\Http\Exception\RequestException

Documentation for the latest version is here: Guzzle request options- connect_timeout, timeout.

最新版本的文档在这里:Guzzle 请求选项- connect_timeout, timeout

回答by Axi

Small precision, you also can define timeouts on Client constructor

小精度,您还可以在 Client 构造函数上定义超时

$client = new Guzzle\Http\Client('', array(
    'request.options' => array (
        'timeout' => 6,
        'connect_timeout' => 6 
    ) 
));

It'll be valid for all requests made from this Client

它将对该客户端发出的所有请求有效

回答by Radu Murzea

The only way I know how to do it in Guzzle is:

我知道如何在 Guzzle 中做到这一点的唯一方法是:

$params = array(
    'command.request_options' = array(
        'timeout'         => 5,
        'connect_timeout' => 2
    )
);

$client = new Client();

$description = ServiceDescription::factory('/path/to/service/description/file');
$client->setDescription($description);

$command = $client->getCommand('commandName', $params);
$command->prepare();

$client->execute($command);

At first glance, Guzzle's documentation seems very good, but I think it's poor, confusing and incomplete. So, for me, is hard to figure out if your code is actually correct and if it should work.

乍一看,Guzzle 的文档似乎很不错,但我认为它很差、很混乱且不完整。所以,对我来说,很难弄清楚你的代码是否真的正确以及它是否应该工作。

回答by Pierre-Yves Gillier

Your example is correct, but it will always fail.

你的例子是正确的,但它总是会失败。

The error is happening on cURL level, not Guzzle. Before sending an HTTP request (Guzzle's job), you need to establish the related IP session (cURL's one). To get the IP session, DNS translation must happen before packets are sent.

错误发生在 cURL 级别,而不是 Guzzle。在发送 HTTP 请求(Guzzle 的工作)之前,您需要建立相关的 IP 会话(cURL 的会话)。要获得 IP 会话,必须在发送数据包之前进行 DNS 转换。

In your example, DNS resolution is failing. It is happening in cURL code, not Guzzle one. So your timeout value won't be used.

在您的示例中,DNS 解析失败。它发生在 cURL 代码中,而不是 Guzzle 代码中。所以你的超时值不会被使用。

If you're still having this error with your real URL, you may add, before your guzzle request, a test which will check if DNS is resolved. Or you may define the following cURL option: CURLOPT_CONNECTTIMEOUT or CURLOPT_CONNECTTIMEOUT_MS (see http://php.net/manual/en/function.curl-setopt.php)

如果您的真实 URL 仍然存在此错误,您可以在您的 guzzle 请求之前添加一个测试,以检查 DNS 是否已解析。或者您可以定义以下 cURL 选项:CURLOPT_CONNECTTIMEOUT 或 CURLOPT_CONNECTTIMEOUT_MS(请参阅http://php.net/manual/en/function.curl-setopt.php

回答by user3665895

Set dns resolve timeout before use guzzle client

在使用 guzzle 客户端之前设置 dns 解析超时

putenv('RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1'); //dns resolve params

$request = $client->get(sprintf("%s/noisesize.api", $this->noiseConfig->url), 
array(
'timeout' => 5, // Response timeout
'connect_timeout' => 5, // Connection timeout
));