php curl_multi批量傳送http請求

loophome發表於2015-10-03

一、使用curl_multi批量傳送http請求

引子:在Android4.0開發中,傳送Http請求已經不允許在主程式中執行了,必須線上程中執行。原因在於Http介面響應時間有可能阻塞主程式事件監聽(對於.Net開發,其實也是如此)。但是,由於PHP並沒有多執行緒的概念,那麼,如何高效率在PHP中執行多次http請求呢?答案是使用curl_multi_init,由此,我做了一個實驗。

以下是模擬請求的http介面,程式碼很簡單,通過get傳入的引數time,控制了sleep的時間。

$s_time = intval($_GET['time']);
sleep($s_time);
echo 'hello';

接下來僅僅使用curl_init,程式碼如下:

$start = microtime(true);
for ($i = 1;$i <= 5;++$i) {
    $ch = curl_init("http://test.binbin.com/curl/test.php?time={$i}");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_exec($ch);
}
$end = microtime(true);
echo $end-$start;
執行的時間約為15秒,是所有sleep時間總和,現在,來看看使用了curl_multi_init的時間

$start = microtime(true);
$ch_list = array();
$multi_ch = curl_multi_init();
for ($i = 1;$i <= 5;++$i) {
    $ch_list[$i] = curl_init("http://test.binbin.com/curl/test.php?time={$i}");
    curl_setopt($ch_list[$i], CURLOPT_RETURNTRANSFER, true);
    curl_multi_add_handle($multi_ch, $ch_list[$i]);
}
$active = null;
do {
    $mrc = curl_multi_exec($multi_ch, $active); //處理在棧中的每一個控制程式碼。無論該控制程式碼需要讀取或寫入資料都可呼叫此方法。
} while ($mrc == CURLM_CALL_MULTI_PERFORM); 
//Note:
//該函式僅返回關於整個批處理棧相關的錯誤。即使返回 CURLM_OK 時單個傳輸仍可能有問題。


while ($active && $mrc == CURLM_OK) {
    if (curl_multi_select($multi_ch) != -1) { //阻塞直到cURL批處理連線中有活動連線。
        do {
        $mrc = curl_multi_exec($multi_ch, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
}
//獲取http返回的結果
foreach ($ch_list as $k => $ch) {
    $result=curl_multi_getcontent($ch);
    curl_multi_remove_handle($multi_ch,$ch);
    curl_close($ch);
}
curl_multi_close($multi_ch);
$end = microtime(true);
echo $end-$start;
結果是僅僅需要5秒鐘,即使最長http請求的執行時間。

後記:curl_errno在curl_multi下即使發生錯誤也無法獲取錯誤碼,可以使用curl_error來獲取錯誤字串,如果沒有發生錯誤,則返回一個空的字串

二、curlmulti系列函式說明

函式名稱 函式說明
curl_multi_init 返回一個新的curl_multi資源控制程式碼,失敗時返回false
curl_multi_add_handle 向curl批處理會話中新增單獨的curl控制程式碼
curl_multi_exec 執行當前 cURL 控制程式碼的子連線
curl_multi_select 等待所有cURL批處理中的活動連線,成功時返回描述符集合中描述符的數量。失敗時,select失敗時返回-1。
curl_multi_getcontent 獲取curl控制程式碼的返回結果內容
curl_multi_close 關閉一個curl_multi資源控制程式碼
curl_multi_info_read 獲取當前解析的cURL的相關傳輸資訊

相關文章