PHP之curl_multi並行詳解方法

2020-07-16 10:05:57

PHP中curl_multi並行詳解

PHP中的curl_multi系列函數可以實現同時請求多個URL來實現並行,而不是像普通curl函數那樣請求後會阻塞,直到結果返回才進行下一個請求。因此在批次請求URL時可通過curl_multi系列函數提升程式的執行效率。

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

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 s

通過對比上述程式的執行時間可以得知,使用curl_multi系列函數並行請求要比普通的curl函數依次請求效率高很多。

推薦教學:《PHP視訊教學

以上就是PHP之curl_multi並行詳解方法的詳細內容,更多請關注TW511.COM其它相關文章!