最近使用 libcurl 遇到的坑

时间:2019-01-11
本文章向大家介绍最近使用 libcurl 遇到的坑,主要包括最近使用 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)。。。。