摘要:今天跑腳本遇到一個奇怪的問題,就是請求到后期會出現程序阻塞卡死,無異常無響應,一直掛起,腳本也不會自動結束。設置允許執行的最長秒數。增加執行超時后的請求設置函數。從錯誤類型中,看到確實是有一些請求在秒內未能執行完畢。
今天跑腳本遇到一個奇怪的問題,就是cURL請求到后期會出現程序阻塞卡死,無異常無響應,一直掛起,腳本也不會自動結束。跟對方溝通后說,“哥們兒,是不是你們的程序有問題啊,這邊研發排查了,說12點30左右沒有收到你們的請求。然后我自己用網上的json工具請求了,一下就通過了”。是不是很尷尬,關鍵是根本不知道為什么。然后就是不停的嘗試重跑腳本,偶爾有些腳本就跑過了,但好景不長,隨時都可能出現無效的時候。一直看,請求一開始都是能正常完成的,越往后執行時間也變得逐漸增長,然后就可能變成死連接。就想到,肯定是cURL發送的請求有的無響應失效了,已經成僵尸連接,還一直阻塞腳本,導致資源一直存在,但是并不能繼續使用。
找了各種資料,還想嘗試寫一個類似定時器的定西,如果腳本執行超過1分鐘,則強制丟棄掉該cURL鏈接。不知道PHP怎么實現這樣的需求,還猶豫要不要用go來實現。涉及到json,xml等,用go畢竟沒有PHP方便,就去手冊閱讀cURL的內容,企圖找到一點有用的東西。而且cURL命令行工具是有重試功能的,猜想擴展肯定也有。但是該如何配置呢?
看了PHP超時處理全面總結這篇文章中的超時,才知道因為我的代碼設置cURL連接選項時只設置了連接超時時間,并沒有設置執行超時時間。觀察通常10秒內正常都應該返回數據,我就設置了超時和執行時間都是30秒。增加這個參數限制后,總算能捕捉到無響應的請求了,剩下的就是如何處理在規定時間內無法返回結果的資源了。
就是這幾個參數沒有了解過,給排查問題浪費了整整一個下午。
/** * CURLOPT_TIMEOUT設置cURL允許執行的最長秒數。 * CURLOPT_TIMEOUT_MS設置cURL允許執行的最長毫秒數。(在cURL7.16.2中被加入。從PHP5.2.3起可使用。) * CURLOPT_CONNECTTIMEOUT在發起連接前等待的時間,如果設置為0,則無限等待。 * CURLOPT_CONNECTTIMEOUT_MS嘗試連接等待的時間,以毫秒為單位。如果設置為0,則無限等待。在cURL7.16.2中被加入。從PHP5.2.3開始可用。 * CURLOPT_DNS_CACHE_TIMEOUT設置在內存中保存DNS信息的時間,默認為120秒。 */
增加執行超時后的請求設置函數。
/** * curl請求 * * @param $url * @param string $postData * @param int $timeout * @return array|mixed * @throws Exception */ protected static function post($url, $postData = "", $timeout = 5) { $ret = array(); $times = 5; do { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HEADER, false); if ($postData != "") { curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); // 重要, 該處不能丟 curl 執行最大秒數 curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); $output = curl_exec($ch); if ($errNo = curl_errno($ch)) { error_log("Error [$errNo]: " . curl_error($ch)); } else { $ret = json_decode($output, true); // 解析的結果集為空時停止查詢 if (!is_array($ret) && !trim($ret)) { throw new Exception(__METHOD__ . ": cURL調用失敗, 信息為: " . $output); } unset($output); } curl_close($ch); if (isset($ret[0]) && $ret[0]) { return $ret; } } while ($times--); exit(__METHOD__ . ": cURL請求重試至 {$times} 次后仍無響應, 執行退出"); }
超時時的提示信息設置如:
error_log("Error [$errNo]: " . curl_error($ch));
我設置的連接時間和執行時間限制都是30秒。
Error [28]: Operation timed out after 30000 milliseconds with 0 bytes received
可以輸出查看,針對這種超時,直接丟棄該次連接,重新初始化一次資源請求即可。當然這里嘗試重試6次,6次都還無法正常執行完畢,就只能在想別的辦法了。雖然最終并不知道為什么會有連接失效,但是這樣之后,就能保證基本可以完成任務了。
我執行一個月的跑數腳本,所有超時情況就有這么多,幸運的是最終都沒能等到重試6次,就請求成功了。從錯誤類型中,看到確實是有一些請求在30秒內未能執行完畢。
Error [28]: Operation timed out after 30000 milliseconds with 0 bytes received Error [28]: Operation timed out after 30000 milliseconds with 0 bytes received Error [28]: Operation timed out after 30000 milliseconds with 62399 out of 323196 bytes received
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/23251.html
視頻地址 學徒卡夫 - 卡夫的Mac 03 - Mac下使用Docker配置PHP環境 https://www.bilibili.com/vide... 安裝 Docker https://www.docker.com/docker... 下載鏡像 # 安裝基礎鏡像 - ubuntu:14.04 # 拉取鏡像(拉取鏡像經常會失敗,嘗試幾次就好了) docker pull ubuntu:14.0...
視頻地址 學徒卡夫 - 卡夫的Mac 03 - Mac下使用Docker配置PHP環境 https://www.bilibili.com/vide... 安裝 Docker https://www.docker.com/docker... 下載鏡像 # 安裝基礎鏡像 - ubuntu:14.04 # 拉取鏡像(拉取鏡像經常會失敗,嘗試幾次就好了) docker pull ubuntu:14.0...
摘要:背景說明小拽利用的寫的爬蟲,實驗性的爬取了知乎用戶的基本信息同時,針對爬取的數據,進行了簡單的分析呈現。本程序抓取的是知乎對外提供用戶訪問的個人信息頁面抓取過程需要攜帶用戶才能獲取頁面。 背景說明:小拽利用php的curl寫的爬蟲,實驗性的爬取了知乎5w用戶的基本信息;同時,針對爬取的數據,進行了簡單的分析呈現。demo 地址 php的spider代碼和用戶dashboard的展現代碼...
摘要:背景說明小拽利用的寫的爬蟲,實驗性的爬取了知乎用戶的基本信息同時,針對爬取的數據,進行了簡單的分析呈現。本程序抓取的是知乎對外提供用戶訪問的個人信息頁面抓取過程需要攜帶用戶才能獲取頁面。 背景說明:小拽利用php的curl寫的爬蟲,實驗性的爬取了知乎5w用戶的基本信息;同時,針對爬取的數據,進行了簡單的分析呈現。demo 地址 php的spider代碼和用戶dashboard的展現代碼...
摘要:背景說明小拽利用的寫的爬蟲,實驗性的爬取了知乎用戶的基本信息同時,針對爬取的數據,進行了簡單的分析呈現。本程序抓取的是知乎對外提供用戶訪問的個人信息頁面抓取過程需要攜帶用戶才能獲取頁面。 背景說明:小拽利用php的curl寫的爬蟲,實驗性的爬取了知乎5w用戶的基本信息;同時,針對爬取的數據,進行了簡單的分析呈現。demo 地址 php的spider代碼和用戶dashboard的展現代碼...
閱讀 2078·2021-10-08 10:21
閱讀 2471·2021-09-29 09:34
閱讀 3494·2021-09-22 15:51
閱讀 4926·2021-09-22 15:46
閱讀 2314·2021-08-09 13:42
閱讀 3434·2019-08-30 15:52
閱讀 2723·2019-08-29 17:13
閱讀 1555·2019-08-29 11:30