php curl請求超時,設置毫秒級解決


問題背景

 由於百度接口的超時設置很大,導致隊列經常堵塞,因此將超時時間縮短為毫秒級別,代碼如下:

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 300); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 500);

問題現象

所有調用此代碼的接口都響應超時,並且響應時間極短

問題解決經過

在網上查資料說要設置這個毫秒級別的超時才會生效:

curl_setopt ( $ch, CURLOPT_NOSIGNAL, true); 

於是本地測試,發現毫無影響:

然后直接在test01上把超時時間加大為一秒以上,發現響應成功
然后改回來,加上那行代碼,響應成功

問題結論

如果要支持毫秒級別的超時設置必須加
curl_setopt ( $ch, CURLOPT_NOSIGNAL, true);
如果只是

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 300); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 500);

將直接返回超時【但是, 我們卻發現, 在我們的CentOS服務器上, 

當你設置了小於1000ms的超時以后, curl不會發起任何請求,
而直接返回超時錯誤(Timeout reached 28)】,這是PHP的坑,資深者直接閱讀這個 http://www.laruence.com/2014/01/21/2939.html
timeout支持毫秒數在cURL 7.16.2中被加入,從PHP 5.2.3起可使用。

 

項目代碼

 /** * 服務器通過get請求獲得內容 * @author duke * @param string $url 請求的url,拼接后的 * @return string 請求返回的內容 */


    private static function get_contents($url, $param) { $baidu_key = self::getOneKey(); $param['ak'] = $baidu_key; $param['output'] = 'json'; $url = $url . '?' . http_build_query($param, '', '&'); //echo $url;
        $retry = 2; $result = array(); while ($retry > 0) { $result = json_decode(self::curl_get($url), true); if (!empty($result) && isset($result['status']) && $result['status'] == 0) { return $result; } if (!empty($result) && isset($result['status'])) { $status = $result['status']; } else { $status = ' http_error:'; } EdjLog::info("baidu_response retry status is" . $status.'params'.json_encode($param)); $retry--; } EdjLog::warning('request to baidu lbs api failed after retries'); return $result; }
private static function curl_get($url, $milliseconds = 300) { $start_time = microtime(true); $ch = curl_init(); //這個參數很重要,設置這個才可以支持毫秒級的超時設置
        curl_setopt($ch, CURLOPT_NOSIGNAL, 1); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); curl_setopt($ch, CURLOPT_USERAGENT, self::$useragent); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_FAILONERROR, 0); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, self::$connecttimeout); curl_setopt($ch, CURLOPT_TIMEOUT_MS, $milliseconds); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_URL, $url); $response = curl_exec($ch); $http_error_code = curl_errno($ch); curl_close($ch); EdjLog::info("request to baidu lbs api, url is $url, cost time:" . (microtime(true) - $start_time)); EdjLog::info("baidu http_error:$http_error_code response is " . str_replace(PHP_EOL, '', $response)); return $response; }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM