最近使用 libcurl 遇到的坑
学艺不精,有待深入学习 Orz
1 curl 请求时间超过1s
最近使用 libcurl 调用内网另一台服务器的一个服务,结果过了 1s 才收到返回包,一开始以为是对方服务出问题,结果对方反馈他们压测的结果是 2~3ms 就能返回结果。排查到最后才发现是 libcurl 的坑,差点因为这个将开发方案驳回。
我是使用post请求发送批量数据到对方的服务,而 libcurl 会默认添加一个请求头 expect: 100-continue,当请求数据包超过 1024 字节时,会先发一个请求信息,等待服务器应答后再发送数据包。如果服务器没有应答,那么会等待 1s 再发送数据包,我们测试的时候所看到的 1s 就是这么来的。
由于我们不能给服务器添加应答的逻辑,就只能修改 curl 请求。解决方法是,添加一个空的请求头,把 expect: 100-continue 请求头干掉就好了:
curl_slist* pHeads= NULL;
pHeads= curl_slist_append(pHeads, "expect: ");
curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pHeads));
2 多线程跑 curl 导致程序 core 掉
上面响应速度慢的问题解决了,然后开心地开发,自测也OK,转测的时候测试同学一压测,gg,程序 core 掉了。。。于是又开启了新的一番查找 bug 的旅程。
折腾了好久,问题定位为,高并发的情况下程序才会 core 掉,由于程序是在现有的服务上添加功能,猜测服务是多线程处理的。问题排查了好久,发现程序其他地方并没有能 core 掉的,于是又把目光转向 libcurl。果不其然,最后发现在设置了 curl 的超时时间后,没有加上 NOSIGNAL 头,导致多线程在 curl 调用服务前解析 DNS 的时候,会有可能同时操作同一个变量,最后程序 core 掉。。。
解决方法是加上 NOSIGNAL:
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(pCurl, CURLOPT_TIMEOUT_MS, 3000);
但是这样又有个问题,添加 NOSIGNAL 后,DNS解析将不会收到超时的限制,要是 DNS 服务器 duang 得一声跪了,那程序就会卡在那里。。。网上的说法是让 libcurl 使用 c-ares,不过具体的我还没试(毕竟程序上线的编译环境我动不了啊,动得了我也不敢动啊 Orz)。。。。
- Golang 基本语法学习笔记之流程控制
- Go 语言的演化历程
- JS 评分五角星随鼠标移动显示
- Golang标准库学习——buffio包 ---转
- 【Go 语言社区】Go语言条件变量的两个例子
- mysqlimport导入报错的排查(r10笔记第58天)
- 【Go 语言社区】POJ 1047 Round and Round We Go 循环数新解
- 【Go 语言社区】删除redis所有KEY
- 【Go 语言社区】Golang 动态实例化结构体
- 【Go 语言社区】Go 错误处理
- 【Go 语言社区】Go 语言范围(Range)
- 【Go 语言社区】JS 相关---Window Location
- 【Go 语言社区】Go 语言Map(集合)
- 【Go 语言社区】JavaScript Date(日期)对象
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux KeyLogger
- [- Flutter 数据&状态篇 -] InheritedWidget
- Android实现图片一边的三角形边框效果
- Android使用SoundPool播放短音效
- 用Jquery做一个进度条
- Android SoundPool实现简短小音效
- [-Flutter趣玩篇-] 出神入化的Align
- Android应用禁止屏幕休眠的3种方法
- Flutter 实现下拉刷新上拉加载的示例代码
- [- C++趣玩篇1 -] 从打印开始说起
- Android实现蓝牙(BlueTooth)设备检测连接
- JQuery 入门学习(三)
- Android实现美团APP的底部滑动菜单
- 正则十八式-第二式:控鹤擒龙
- android实现手写签名功能