文档章节

Curl的毫秒超时的一个”Bug”

BearCatYN
 BearCatYN
发布于 2015/04/29 12:20
字数 666
阅读 132
收藏 5
点赞 0
评论 0

最近我们的服务在升级php使用的libcurl, 期望新版本的libcurl支持毫秒级的超时, 从而可以更加精细的控制后端的接口超时, 从而提高整体响应时间.

但是, 我们却发现, 在我们的CentOS服务器上, 当你设置了小于1000ms的超时以后, curl不会发起任何请求, 而直接返回超时错误(Timeout reached 28).

原来, 这里面有一个坑, CURL默认的, 在Linux系统上, 如果使用了系统标准的DNS解析, 则会使用SIGALARM来提供控制域名解析超时的功能, 但是SIGALARM不支持小于1s的超时, 于是在libcurl 7.28.1的代码中(注意中文注释行):

int Curl_resolv_timeout(struct connectdata *conn,
                        const char *hostname,
                        int port,
                        struct Curl_dns_entry **entry,
                        long timeoutms)
{
.......
.......
#ifdef USE_ALARM_TIMEOUT
  if(data->set.no_signal)
    /* Ignore the timeout when signals are disabled */
    timeout = 0;
  else
    timeout = timeoutms;
 
  if(!timeout)
    /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
    return Curl_resolv(conn, hostname, port, entry);
 
  if(timeout < 1000) //如果小于1000, 直接超时返回
    /* The alarm() function only provides integer second resolution, so if
       we want to wait less than one second we must bail out already now. */
    return CURLRESOLV_TIMEDOUT;
 
  ....
  ....

可见, 当你的超时时间小于1000ms的时候, name解析会直接返回CURLRESOLV_TIMEOUT, 最后会导致CURLE_OPERATION_TIMEDOUT, 然后就Error, Timeout reached了…

这….太坑爹了吧? 难道说, 我们就不能使用毫秒超时么? 那你提供这功能干啥?

还是看代码, 还是刚才那段代码, 注意这个(中文注释行):

#ifdef USE_ALARM_TIMEOUT
  if(data->set.no_signal)  //注意这行
    /* Ignore the timeout when signals are disabled */
    timeout = 0;
  else
    timeout = timeoutms;
 
  if(!timeout)
    /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
    return Curl_resolv(conn, hostname, port, entry);
 
  if(timeout < 1000)
    /* The alarm() function only provides integer second resolution, so if
       we want to wait less than one second we must bail out already now. */
    return CURLRESOLV_TIMEDOUT;

看起来, 只要set.no_signal 这个东西为1, 就可以绕过了… 那这个玩意是啥呢?

这就简单了, grep一下代码, 发现:

 
  case CURLOPT_NOSIGNAL:
    /*
     * The application asks not to set any signal() or alarm() handlers,
     * even when using a timeout.
     */
    data->set.no_signal = (0 != va_arg(param, long))?TRUE:FALSE;
    break;

哈哈, 原来是这货:

<?php
   curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
?>

加上这个OPT以后, 一切终于正常了!

后记:

这样一来, 就会有一个隐患, 那就是DNS解析将不受超时限制了, 这在于公司内部来说, 一般没什么问题, 但是万一DNS服务器hang住了, 那就可能会造成应用超时.

那么还有其他办法么?

有, 那就是Mike提醒的, 我们可以让libcurl使用c-ares(C library for asynchronous DNS requests)来做名字解析. 具体的可以在config curl的时候:


本文转载自:http://www.laruence.com/2014/01/21/2939.html

共有 人打赏支持
BearCatYN
粉丝 27
博文 158
码字总数 11947
作品 0
朝阳
程序员
阅读鸟哥的风雪之隅PHP博客的笔记(1)

在PHP中使用协程实现多任务调度 http://www.laruence.com/2015/05/28/3038.html 2. Curl的毫秒超时的一个”Bug” CentOS服务器上, 当你设置了小于1000ms的超时以后, curl不会发起任何请求, 而...

laiconglin
2016/06/12
45
0
为什么你必须得学些 TCP/IP 的知识?

题外话:通信通讯三次握手?你还在停留在这个级别么,对于专业网络者和开发者而言,同步和异步的通信变得更加重要和迫切。 这不是指要明白 TCP 的所有东西,也不是说要通读 《TCP/IP 详解》。...

English0523
2016/01/12
0
0
PHP也玩并发,巧用curl 并发减少后端访问时间

说明:本人源自3篇博文 http://blog.csdn.net/zuiaituantuan/article/details/7048782 首先,先了解下 php中的curl多线程函数: # curlmultiaddhandle # curlmulticlose # curlmultiexec # ......

晨曦之光
2012/03/09
8.5K
0
curl的设置超时时间小于1000ms时无效

curl版本>7.16.2,支持CURLOPTTIMEOUTMS,请求响应时间很小,小于5ms,设置CURLOPTTIMEOUTMS为120ms,不能正确得到响应。要做一个实时竞价的东西,往外发几个百请求,目前用的是curlmultiex...

Zone
2011/04/08
1K
0
curl连接时间设置

CURL访问HTTP: CURL 是常用的访问HTTP协议接口的lib库,性能高,还有一些并发支持的功能等。 curl_setopt($ch, opt) 可以设置一些超时的设置,主要包括: (重要) CURLOPT_TIMEOUT 设置cURL允...

colin_86
2015/10/23
3
0
世界最著名的四大bug

世界最著名的四大bug 程序师2018-01-030 阅读 bug业界观察 “电子邮件无法发送到 500 英里以外” Bug界最经典的传奇之一 我在做校园的邮件系统管理员的时候,有用户向我抱怨说:他们不能发送...

程序师
01/03
0
0
有一些bug,她们来自异次元,却与你情定三生

西雅图IT圈:seattleit 【今日作者】littlelann 一个充满着人文情怀的web前端相声演员 有那么一些bug 她们来自异次元 那么遥远 却又如此地贴近生活 “电子邮件无法发送到 500 英里以外” Bu...

m68futkmurmtj
2017/12/30
0
0
JDK中的URLConnection参数详解

针对JDK中的URLConnection连接Servlet的问题,网上有虽然有所涉及,但是只是说明了某一个或几个问题,是以FAQ的方式来解决的,而且比较零散,现在对这个类的使用就本人在项目中的使用经验做如下...

gaofeng36599
2017/07/14
0
0
HTTPOXY漏洞说明

19 Jul 16 HTTPOXY漏洞说明 作者: Laruence( ) 本文地址: http://www.laruence.com/2016/07/19/3101.html 转载请注明出处 好久没写文章了, 博客都长草了, 早上起来本来想去上班, 一看这么...

Laruence
2017/12/21
0
0
HttpURLConnection用法详解

针对JDK中的URLConnection连接Servlet的问题,网上有虽然有所涉及,但是只是说明了某一个或几个问题,是以FAQ的方式来解决的,而且比较零散,现在对这个类的使用就本人在项目中的使用经验做如下...

一别经年
2014/01/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

如何把你的Linux系统变的更加安全

做为一个小白,以为自己懂了点Linux知识,会搭建Linux各种服务就觉得自己牛的不要要的。在我们团队里面,我将使用了一台破电脑搭建Linux服务器,上面跑着Ftp服务存放着资源,ssh服务可以远程...

问题终结者
2分钟前
0
0
lombok的使用和原理

一、项目背景 在写Java程序的时候经常会遇到如下情形: 新建了一个Class类,然后在其中设置了几个字段,最后还需要花费很多时间来建立getter和setter方法 lombok项目的产生就是为了省去我们手...

颖辉小居
2分钟前
0
0
rsync至服务同步-系统日志-screen

rsync: 服务同步;配置文件:/etc/rsyncd.conf 默认端口:873 服务启动:rsync --daemon rsync -av /root/1.txt 192.168.1.2::test/2.txt (test为模块名称) /etc/rsync.conf配置样例: #指定...

ZHENG-JY
4分钟前
0
0
读取文件中内容转换成字符串

package com.lieni.ruyu.api.xmlTool; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Unsuppo......

newdeng
4分钟前
0
0
《PHP和MySQL Web 开发》 第8章 设计Web数据库

LCL WARNING 这是我学习《PHP和MySQL Web 开发》的读书笔记,一些重要的知识点我会记录下来,当然只会写我觉得重要的。 如果有幸有人看到这个学习笔记了,你要结合着书看,不要光看这个笔记。...

十万猛虎下画山
11分钟前
0
0
Spring+jpaNo transactional EntityManager available

TransactionRequiredException: No transactional EntityManager availableEntityManager执行以下方法(refresh, persist, flush, joinTransaction, remove, merge) 都需要需要事务i......

wpfc
12分钟前
0
0
八幅漫画理解使用JSON Web Token设计单点登录系统

八幅漫画理解使用JSON Web Token设计单点登录系统 Sep 07, 2015 in Engineering 上次在《JSON Web Token - 在Web应用间安全地传递信息》中我提到了JSON Web Token可以用来设计单点登录系统。...

祖冲之
14分钟前
0
0
Spring框架中的设计模式(三)

Spring框架中的设计模式(三) 原创: 瑞查德-Jack 在之前的两篇文章中,我们看到了一些在Spring框架中实现的设计模式。这一次我们会发现这个流行框架使用的3种新模式。 本文将从描述两个创意...

瑞查德-Jack
17分钟前
1
0
[MicroPython]TPYBoard智能小车“飞奔的TPYBoard装甲一号”

智能小车作为现代的新发明,是以后的发展方向,他可以按照预先设定的模式在一个环境里自动的运作,不需要人为的管理,可应用于科学勘探等等的用途。智能小车能够实时显示时间、速度、里程,具...

bodasisiter
19分钟前
0
0
桌面虚拟化VDI(Virtual Desktop Infrastructure)

为了保证员工(客户)不把公司的资料复制、传输给别人。可以把员工平时办公放在服务器上做。所以使用桌面虚拟化。就是把一个服务器虚拟出很多桌面系统(如:windows)。 桌面虚拟化最大的优势...

王坤charlie
26分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部