當前位置: 首頁> 最新文章列表> 如何結合curl_multi_exec() 和curl_share_init() 實現並發請求優化

如何結合curl_multi_exec() 和curl_share_init() 實現並發請求優化

M66 2025-05-18

在現代Web開發中,處理大量HTTP請求是常見需求,例如批量抓取接口數據、並行下載資源、檢查鏈接狀態等。傳統的串行請求方式(即一個請求結束後再發起下一個)效率低下。為此,PHP提供了curl_multi_*系列函數來實現並發請求,而curl_share_*系列則可以在多個cURL句柄間共享資源(如DNS緩存),進一步優化性能。本文將介紹如何結合curl_multi_exec()curl_share_init()來實現高效並發請求優化。

1?? 為什麼要使用curl_multi_*?

curl_multi_*系列函數允許我們同時發送多個HTTP請求,而不是一個一個排隊等候。其核心工作流程是:

  1. 初始化一個multi handle ( curl_multi_init )。

  2. 將多個easy handle ( curl_init ) 加入到multi handle。

  3. 使用curl_multi_exec()驅動並發請求。

  4. 使用curl_multi_select()等待活動句柄(避免CPU空轉)。

  5. 收集結果並關閉資源。

這種方式尤其適合需要同時處理大量請求的場景,比如爬蟲、接口聚合、CDN預熱等。

2?? 什麼是curl_share_*?為什麼要結合使用?

雖然curl_multi_*可以並發請求,但每個easy handle 默認是獨立的,例如每個都要單獨解析DNS、維護自己的cookie等。 curl_share_*系列函數允許多個easy handle 共享某些內部資源(如DNS緩存、SSL會話、cookie等),這樣可以避免重複工作,提高性能並減少內存開銷。

核心步驟包括:

  1. 使用curl_share_init()創建一個共享對象。

  2. 使用curl_share_setopt()設置共享的內容(如CURLSHOPT_SHARE)。

  3. 使用curl_setopt($ch, CURLOPT_SHARE, $share)將共享對象附加到easy handle。

  4. 請求完成後釋放共享對象。

3?? 完整示例:並發請求+ 共享DNS緩存

下面提供一個實際可運行的PHP代碼示例:

 <?php

// 需要並發請求的URL列表
$urls = [
    'https://m66.net/api/endpoint1',
    'https://m66.net/api/endpoint2',
    'https://m66.net/api/endpoint3',
    'https://m66.net/api/endpoint4'
];

// 初始化 multi handle
$multiHandle = curl_multi_init();

// 創建共享對象
$shareHandle = curl_share_init();
curl_share_setopt($shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);

// 存儲各個 easy handle
$curlHandles = [];

foreach ($urls as $url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SHARE, $shareHandle);
    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[$url] = $ch;
}

// 執行並發請求
$active = null;
do {
    $mrc = curl_multi_exec($multiHandle, $active);
    if ($mrc == CURLM_CALL_MULTI_PERFORM) {
        continue;
    }
    curl_multi_select($multiHandle);
} while ($active && $mrc == CURLM_OK);

// 收集結果
$responses = [];
foreach ($curlHandles as $url => $ch) {
    $responses[$url] = curl_multi_getcontent($ch);
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}

// 關閉 multi handle 和 share handle
curl_multi_close($multiHandle);
curl_share_close($shareHandle);

// 打印結果
foreach ($responses as $url => $content) {
    echo "Response from $url:\n";
    echo $content . "\n\n";
}

4?? 優化要點總結

?使用curl_multi_提高並發性能*:同時發起和處理多個請求,顯著減少總耗時。
?利用curl_share_節省重複開銷*:通過共享DNS緩存等資源,避免重複解析,提高整體效率。
?注意資源釋放:請求完成後,記得釋放每個easy handle、multi handle 和share handle,否則可能導致內存洩漏。
?結合curl_multi_select() :等待網絡活動,避免CPU佔用100%。

5?? 適用場景

  • 高並發接口聚合請求。

  • 大量頁面或文件的批量抓取。

  • 網站監控、健康檢查。

  • CDN或緩存預熱。

結合使用curl_multi_exec()curl_share_init() ,不僅可以實現真正的並發,還能通過資源共享減少重複工作,讓PHP在處理高並發網絡請求時更加高效穩定。

如果你在實際應用中遇到優化瓶頸,還可以進一步結合連接池、任務調度、異常處理等手段來完善整體方案。