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

-- PHP老杨

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

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

原来, 这里面有一个坑, 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 = ;

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;

....

....

可见, 当你的超时时间小于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 = ;

else

timeout = timeoutms;

if(!timeout)

/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */

return Curl_resolv(conn, hostname, port, entry);

if(timeout < )

/* 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 = ( != va_arg(param, long))?TRUE:FALSE;

break;

哈哈, 原来是这货:

<?php

curl_setopt($ch, CURLOPT_NOSIGNAL, );

?>

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

后记:

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

那么还有其他办法么?

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

./configure --enable-ares[=PATH]

这样就可以不用设置NOSIGNAL了 
 

Curl的毫秒超时的一个”Bug”的更多相关文章

  1. curl毫秒超时使用的坑

    升级后的libcurl已经支持了毫米级别的超时.但是使用的时候还有一个坑需要注意跨过去 . libcurl如果检查到设置的timeout < 1s 那么会直接发出一个信号说 "已经超时 ...

  2. 我是一个Bug, 终极大Bug

    我是一个Bug ,在这个系统中潜伏很久了,历经多轮测试的严酷考验而屹立不倒,如果Bug界按难度分类的话,我绝对属于地狱模式. 现在,我就等待一个倒霉蛋来触发, 可是他老是不来. 其实不能叫倒霉蛋 , ...

  3. Tomcat一个BUG造成CLOSE_WAIT

    之前应该提过,我们线上架构整体重新架设了,应用层面使用的是Spring Boot,前段日子因为一些第三方的原因,略有些匆忙的提前开始线上的内测了.然后运维发现了个问题,服务器的HTTPS端口有大量的C ...

  4. MySQL关于exists的一个bug

    今天碰到一个很奇怪的问题,关于exists的, 第一个语句如下: SELECT ) FROM APPLY t WHERE EXISTS ( SELECT r.APPLY_ID FROM RECORD ...

  5. 由一个bug引发的SQLite缓存一致性探索

    问题 我们在生产环境中使用SQLite时中发现建表报“table xxx already exists”错误,但DB文件中并没有该表.后面才发现这个是SQLite在实现过程中的一个bug,而这个bug ...

  6. Win10系统菜单打不开问题的解决,难道是Win10的一个Bug ?

    Win10左下角菜单打不开,好痛苦,点击右下角的时间也没反应,各种不爽,折磨了我好几天,重装又不忍心,实在费劲,一堆开发环境要安装,上网找了很多方法都不适用.今天偶然解决了,仔细想了下,难道是Win1 ...

  7. 你可能不知道的 NaN 以及 underscore 1.8.3 _.isNaN 的一个 BUG

    这篇文章并不在我的 underscore 源码解读计划中,直到 @pod4g 同学回复了我的 issue(详见 https://github.com/hanzichi/underscore-analy ...

  8. 标准模板库(STL)的一个 bug

    今天敲代码的时候遇到 STL 的一个 bug,与 C++ 的类中的 const 成员变量有关.什么,明明提供了默认的构造函数和复制构造函数,竟然还要类提供赋值运算符重载.怎么会这样? 测试代码 Tes ...

  9. 是uibutton跟tableviewcell同步使用一个bug

    这个问题是uibutton跟tableviewcell同步使用一个bug,不关delay一点毛事,证据就是点击事件没问题,so,搜到一个方法解决了这个问题.uibutton分类symbian2+ios ...

随机推荐

  1. (转)消息中间件的技术选型心得-RabbitMQ、ActiveMQ和ZeroMQ

    RabbitMQ.ActiveMQ和ZeroMQ都是极好的消息中间件,但是我们在项目中该选择哪个更适合呢?很多开发者面临这个烦恼.下面我会对这三个消息中间件做一个比较,看了后你们就心中有数了. Rab ...

  2. javascript之基本包装类型(Boolean,Number,String)基础篇

    前几天整理了javascript中Array方面的知识,但是String中的一些方法多多少少和Array里的方法有些类似容易混淆,就顺便连同String所在的包装类一起整理一下,希望可以帮助到初学者, ...

  3. ThinkPHP快速入门

    ThinkPHP快速入门 1.ThinkPHP自动生成 当我们部署完ThinkPHP框架后,其会自动生成Application文件夹,如下图所示: 2.自动生成细节分析 问题1:Application ...

  4. The Name/Origin of Country names

    1.Puerto Rico (Spanish for "Rich Port"/富裕的港口/富港 ) 2.HongKong(Chinese for "香港")

  5. DailyWallpaper - V1.01 released

    桌面每日一图 最近发现美国国家地理网站上有个photo of the day很不错,地址在这里.http://photography.nationalgeographic.com/photograph ...

  6. AndroidStudio支持新的NDK的操作使用

    在2015的Google I / O大会,5月底,谷歌宣布了一项新的支持由Android NDK Studio 1.3,Jetbrains CLion集成功能,Android gradle插件.这种支 ...

  7. JQuery在iframe中实现 点击后选中当前栏目的样式

    二级或者三级折叠菜单参考http://www.cnblogs.com/qigege/p/5178947.html <script type="text/javascript" ...

  8. php读取图片内容并输出到浏览器的实现代码

    如果php以图片,zip,exe等文件输出到浏览器,而前面还输出了其他字符,就会有乱码. 代码很简单,网上都能找到,但在我机子上就是显示不出来,显示出的一直是这个php文件路径,费了点时间才搞定,原来 ...

  9. Crusher Django 学习笔记4 使用Model

    http://crusher-milling.blogspot.com/2013/09/crusher-django-tutorial4-using-basic.html 顺便学习一下FQ Crush ...

  10. Excel中的宏--VBA的简单例子

    第一步:点击录制宏 第二步:填写宏的方法名 第三步:进行一系列的操作之后,关闭宏 第四步:根据自己的需要查看,修改宏 第六步:保存,一般是另存为,后缀名为.xlsm,否则宏语言不能保存. 到此为止恭喜 ...