最近使用 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)。。。。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章