PHP中curl_multi併發詳解

PHP中的curl_multi系列函數能夠實現同時請求多個URL來實現併發,而不是像普通curl函數那樣請求後會阻塞,直到結果返回才進行下一個請求。所以在批量請求URL時可經過curl_multi系列函數提高程序的運行效率。php

curl普通請求

$startTime = microtime(true);
$chArr = [];
$optArr = [
    CURLOPT_URL => 'http://www.httpbin.org/ip',
    CURLOPT_HEADER => 0,
    CURLOPT_RETURNTRANSFER => 1,
];
$result = [];

//建立多個curl資源並執行
for ($i=0; $i<10; $i++) {
    $chArr[$i] = curl_init();
    curl_setopt_array($chArr[$i], $optArr);
    $result[$i] = curl_exec($chArr[$i]);
    curl_close($chArr[$i]);
}

$endTime = microtime(true);
echo sprintf("use time: %.3f s".PHP_EOL, $endTime - $startTime);
複製代碼

use time: 6.080 s併發

curl_multi併發請求

$startTime = microtime(true);
$chArr = [];
$optArr = [
    CURLOPT_URL => 'http://www.httpbin.org/ip',
    CURLOPT_HEADER => 0,
    CURLOPT_RETURNTRANSFER => 1,
];
$result = [];

//建立多個curl資源
for ($i=0; $i<10; $i++) {
    $chArr[$i] = curl_init();
    curl_setopt_array($chArr[$i], $optArr);
}
//建立批處理curl句柄
$mh = curl_multi_init();
//將單個curl句柄添加到批處理curl句柄中
foreach ($chArr as $ch) {
    curl_multi_add_handle($mh, $ch);
}
//判斷操做是否仍在執行的標識的引用
$active = null;
/** * 本次循環第一次處理 $mh 批處理中的 $ch 句柄,並將 $mh 批處理的執行狀態寫入 $active, * 當狀態值等於 CURLM_CALL_MULTI_PERFORM 時,代表數據還在寫入或讀取中,執行循環, * 當第一次 $ch 句柄的數據寫入或讀取成功後,狀態值變爲 CURLM_OK ,跳出本次循環,進入下面的大循環中。 */
do {
    //處理在批處理棧中的每個句柄
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
/** * 上面這段代碼中,是能夠直接使用 $active > 0 來做爲 while 的條件,以下: * do { * $mrc = curl_multi_exec($mh, $active); * } while ($active > 0); * 此時若是整個批處理句柄沒有所有執行完畢時,系統會不停的執行 curl_multi_exec 函數,從而致使系統CPU佔用會很高, * 所以通常不採用這種方案,能夠經過 curl_multi_select 函數來達到沒有須要讀取的程序就阻塞住的目的。 */

/** * $active 爲 true 時,即 $mh 批處理之中還有 $ch 句柄等待處理, * $mrc == CURLM_OK,即上一次 $ch 句柄的讀取或寫入已經執行完畢。 */
while ($active && $mrc == CURLM_OK) {
    /** * 程序進入阻塞狀態,直到批處理中有活動鏈接(即 $mh 批處理中還有可執行的 $ch 句柄), * 這樣執行的好處是 $mh 批處理中的 $ch 句柄會在讀取或寫入數據結束後($mrc == CURLM_OK)進入阻塞階段, * 而不會在整個 $mh 批處理執行時不停地執行 curl_multi_exec 函數,白白浪費CPU資源。 */
     if (curl_multi_select($mh) != -1) {
        //程序退出阻塞狀態繼續執行須要處理的 $ch 句柄
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
}

foreach ($chArr as $i=>$ch) {
    //獲取某個curl句柄的返回值
    $result[$i] = curl_multi_getcontent($ch);
    //移除批處理句柄中的某個句柄資源
    curl_multi_remove_handle($mh, $ch);
}
//關閉一組curl句柄
curl_multi_close($mh);
$endTime = microtime(true);
echo sprintf("use time: %.3f s".PHP_EOL, $endTime - $startTime);
複製代碼

use time: 0.599 scurl

經過對比上述程序的運行時間能夠得知,使用curl_multi系列函數併發請求要比普通的curl函數依次請求效率高不少。函數

相關文章
相關標籤/搜索