PHPCurl的毫秒逾時的一個”Bug”_PHP教程

來源:互聯網
上載者:User
最近我們的服務在升級php使用的libcurl, 期望新版本的libcurl支援毫秒級的逾時, 從而可以更加精細的控制後端的介面逾時, 從而提高整體回應時間.

但是, 我們卻發現, 在我們的CentOS伺服器上, 當你設定了小於1000ms的逾時以後, curl不會發起任何請求, 而直接返回逾時錯誤(Timeout reached 28).

原來, 這裡面有一個坑, 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 = 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;

哈哈, 原來是這貨:


  • curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
  • ?>

加上這個OPT以後, 一切終於正常了!

後記:

這樣一來, 就會有一個隱患, 那就是DNS解析將不受逾時限制了, 這在於公司內部來說, 一般沒什麼問題, 但是萬一DNS伺服器hang住了, 那就可能會造成應用逾時.

那麼還有其他辦法麼?

有, 那就是Mike提醒的, 我們可以讓libcurl使用c-ares(C library for asynchronous DNS requests)來做名字解析. 具體的可以在config curl的時候:


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

這樣就可以不用設定NOSIGNAL了

PS, 為什麼冠以”Bug”, 我只是好奇, 他們為什麼不用setitimer?

參考: http://stackoverflow.com/questions/7987584/curl-timeout-less-than-1000ms-always-fails
作者: Laruence
本文地址: http://www.laruence.com/2014/01/21/2939.html

http://www.bkjia.com/PHPjc/735044.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/735044.htmlTechArticle最近我們的服務在升級php使用的libcurl, 期望新版本的libcurl支援毫秒級的逾時, 從而可以更加精細的控制後端的介面逾時, 從而提高整體響應...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.