Curl的毫秒超时的一个”Bug”
浏览:1695次 出处信息
最近我们的服务在升级php使用的libcurl, 期望新版本的libcurl支持毫秒级的超时, 从而可以更加精细的控制后端的接口超时, 从而提高整体响应时间.
但是, 我们却发现, 在我们的CentOS服务器上, 当你设置了小于1000ms的超时以后, curl不会发起任何请求, 而直接返回超时错误(Timeout reached 28).
原来, 这里面有一个坑, CURL默认的, 在Linux系统上, 使用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以后, 一切终于正常了!
最后, 这个我想是Curl的一个bug吧, 只不过我们没想明白他们为啥不用setitimer…
参考: http://stackoverflow.com/questions/7987584/curl-timeout-less-than-1000ms-always-fails
建议继续学习:
- Rolling cURL: PHP并发最佳实践 (阅读:10441)
- curl 命令使用cookie (阅读:8769)
- curl检查访问网页返回的状态码 (阅读:6602)
- ssh连接超时解决办法 (阅读:4553)
- PHP用CURL伪造IP和来源 (阅读:4369)
- curl测试下载速度 (阅读:4214)
- cURL基础教程 (阅读:3924)
- javascript 在各个浏览器中的超时时间 (阅读:4036)
- curl快速实现网速测试 (阅读:3807)
- php socket为什么这么慢,直到超时 (阅读:3964)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
扫一扫订阅我的微信号:IT技术博客大学习
<< 前一篇:如何让 PHP json_encode 函数不转义中文?
后一篇:PHP最佳实践之PHP标签 >>
文章信息
- 作者:雪候鸟 来源: 风雪之隅
- 标签: Curl 超时
- 发布时间:2014-11-23 21:42:10
建议继续学习
近3天十大热文
- [69] Twitter/微博客的学习摘要
- [68] IOS安全–浅谈关于IOS加固的几种方法
- [66] 如何拿下简短的域名
- [65] android 开发入门
- [63] find命令的一点注意事项
- [62] Go Reflect 性能
- [61] 流程管理与用户研究
- [60] Oracle MTS模式下 进程地址与会话信
- [59] 图书馆的世界纪录
- [57] 读书笔记-壹百度:百度十年千倍的29条法则