PHP cURL:CURLOPT_CONNECTTIMEOUT 与 CURLOPT_TIMEOUT
Posted
技术标签:
【中文标题】PHP cURL:CURLOPT_CONNECTTIMEOUT 与 CURLOPT_TIMEOUT【英文标题】:PHP cURL: CURLOPT_CONNECTTIMEOUT vs CURLOPT_TIMEOUT 【发布时间】:2015-03-02 18:57:46 【问题描述】:php 有这两个与超时相关的选项:CURLOPT_CONNECTTIMEOUT
和 CURLOPT_TIMEOUT
。
PHP 网站上的描述有点模糊。有什么区别?
举一个现实世界的例子:假设您通过 cURL 将 GET vars 发送到一个 URL,并且您希望接收一个 XML 返回,CURLOPT_CONNECTTIMEOUT
是否与连接到服务器所需的最长时间有关和CURLOPT_TIMEOUT
发送回 XML 所需的最长时间?
【问题讨论】:
还有 CURLOPT_TIMEOUT_MS。我不确定当同时定义 CURLOPT_TIMEOUT_MS 和 CURLOPT_TIMEOUT 时会发生什么。我想应该定义两者中的任何一个。 @SandeepanNath 来自CURL docs for CURLOPT_TIMEOUT,它指出,“如果同时设置了 CURLOPT_TIMEOUT 和 CURLOPT_TIMEOUT_MS,则将使用最后设置的值。” 【参考方案1】:接受的答案不正确。有关正确的文档,请参阅 Everything CURL 文档。
连接时间基本上涵盖了建立http连接的两个方面:
DNS 解析 tcp 连接建立之前的时间。CURLOPT_TIMEOUT 或 CURLOPT_TIMEOUT_MS 选项根本没有涵盖这段时间。这些涵盖了在我们开始通过刚刚在连接阶段建立的 TCP 连接上的 HTTP 之后发生的所有事情。
这种区别给很多人带来了问题,但它确实允许设置一个相对较短的连接超时,因为如果服务器完全不可用,为什么还要等待呢?但是,如果服务的预期响应时间难以预测,您仍然可以将请求超时设置为相当长的时间。
一般来说,对于生产设置,CURLOPT_CONNECTION_TIMEOUT 应小于 5 秒,CURLOPT_TIMEOUT 应尽可能低(不会导致您经常丢弃请求)。
【讨论】:
【参考方案2】:CURLOPT_CONNECTTIMEOUT 是仅连接到服务器的时间。
CURLOPT_TIMEOUT 是整个连接时间加上交换数据的时间。
因此,CURLOPT_TIMEOUT 始终包含 CURLOPT_CONNECTTIMEOUT。
使用 CURLINFO_CONNECT_TIME 和 CURLINFO_TOTAL_TIME 验证是否非常容易。
curl_getinfo($ch, CURLINFO_CONNECT_TIME) 获取信息,curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $yourMaxConnTime) 设置要连接的最大值。
curl_getinfo($ch, CURLINFO_TOTAL_TIME) 获取信息,curl_setopt($ch, CURLOPT_TIMEOUT, $yourMaxTotTime) 设置整个操作的最大值。
当然,$yourMaxTotTime 必须始终高于 $yourMaxConnTime。 所有这些值都以秒为单位。
【讨论】:
【参考方案3】:除了accepted answer。
根据source code 设置已连接:如果两者都设置,则使用最严格的设置。但仅限于连接阶段。
/* if a timeout is set, use the most restrictive one */
if(data->set.timeout > 0)
timeout_set |= 1;
if(duringconnect && (data->set.connecttimeout > 0))
timeout_set |= 2;
switch(timeout_set)
//...
case 3:
if(data->set.timeout < data->set.connecttimeout)
timeout_ms = data->set.timeout;
else
timeout_ms = data->set.connecttimeout;
break;
Unit tests 表示来源
【讨论】:
【参考方案4】:CURLOPT_CONNECTTIMEOUT 不是由 CURLOPT_TIMEOUT 表示的时间段
如果 CURLOPT_CONNECTTIMEOUT 设置为 3 秒,CURLOPT_TIMEOUT 设置为 4 秒,则执行最多可能需要 7 秒。
我通过模拟慢速服务器连接(iptables drop)对此进行了测试。
【讨论】:
我想我可以确认一下。我已将CURLOPT_TIMEOUT
配置为4
并保持CURLOPT_CONNECTTIMEOUT
不变。我还为超过 10 秒的请求配置了 PHP 慢日志。我的 PHP 脚本连接到远程站点,并且慢速日志经常报告 curl_exec()
花费超过 10 秒的问题。我会假设它仅限于手册中的4
。
你看过这个comment 吗?
根据我在源代码中阅读的内容,这是不正确的,但是如果您通过实验验证它,那将表明不同版本中存在不同的实现......然而GitHub上的版本并没有12 年改变了这个功能。【参考方案5】:
CURLOPT_CONNECTTIMEOUT 是允许与服务器建立连接的最长时间(以秒为单位)。 可以将其设置为 0 以禁用此限制,但在生产环境中不建议这样做。
CURLOPT_TIMEOUT 是单个 cURL 扩展函数调用的执行将被限制的最长时间(以秒为单位)。 请注意,此设置的值应包括 CURLOPT_CONNECTTIMEOUT 的值。
换句话说, CURLOPT_CONNECTTIMEOUT是CURLOPT_TIMEOUT所代表的时间段,所以CURLOPT_TIMEOUT的值应该大于CURLOPT_CONNECTTIMEOUT的值。
来自Difference between CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT
【讨论】:
我想说,这并不正确。 Here 它说,CURLOPT_TIMEOUT
定义了“您允许 libcurl 传输操作花费的最长时间(以秒为单位)。”。这有点模棱两可。我的经验似乎证实了 Miloš 在下面的回答:CURLOPT_CONNECTTIMEOUT
实际上只适用于连接阶段,CURLOPT_TIMEOUT
是适用于传输阶段。两者都添加了定义curl_exec()
的完整超时。
为了说明这一点,让我补充一下这个解释。 CURL_CONNECTIONTIMEOUT 是您已经连接时可以保留连接的最长时间。而 CURL_TIMEOUT 是无法建立连接时您可以从开始到结束尝试的最长时间。
-1,使用的来源是一个不正确的非权威博客,如那里自己的cmets和这里的其他答案所示
如前所述,CURL_CONNECTIONTIMEOUT 是连接阶段,CURLOPT_TIMEOUT 是从最终连接到数据传输结束的一切。常见的方法可能是每次尝试失败时逐渐增加连接超时,但将传输超时保持较高,以免等待无效连接的时间过长
我扫描了 CURL 源代码以确定,它似乎证实了这个答案。如果只设置了 CURLOPT_CONNECTTIMEOUT,那么只有连接阶段会受到它的影响。如果只设置了 CURLOPT_TIMEOUT,那么它适用于整个 curl 操作,包括连接。但是,如果两者都设置,则连接阶段使用两个超时中较短的一个。见curl/lib/connect.c
中的函数Curl_timeleft()
。以上是关于PHP cURL:CURLOPT_CONNECTTIMEOUT 与 CURLOPT_TIMEOUT的主要内容,如果未能解决你的问题,请参考以下文章