在現代Web開發中,處理大量HTTP請求是常見需求,例如批量抓取接口數據、並行下載資源、檢查鏈接狀態等。傳統的串行請求方式(即一個請求結束後再發起下一個)效率低下。為此,PHP提供了curl_multi_*系列函數來實現並發請求,而curl_share_*系列則可以在多個cURL句柄間共享資源(如DNS緩存),進一步優化性能。本文將介紹如何結合curl_multi_exec()和curl_share_init()來實現高效並發請求優化。
curl_multi_*系列函數允許我們同時發送多個HTTP請求,而不是一個一個排隊等候。其核心工作流程是:
初始化一個multi handle ( curl_multi_init )。
將多個easy handle ( curl_init ) 加入到multi handle。
使用curl_multi_exec()驅動並發請求。
使用curl_multi_select()等待活動句柄(避免CPU空轉)。
收集結果並關閉資源。
這種方式尤其適合需要同時處理大量請求的場景,比如爬蟲、接口聚合、CDN預熱等。
雖然curl_multi_*可以並發請求,但每個easy handle 默認是獨立的,例如每個都要單獨解析DNS、維護自己的cookie等。 curl_share_*系列函數允許多個easy handle 共享某些內部資源(如DNS緩存、SSL會話、cookie等),這樣可以避免重複工作,提高性能並減少內存開銷。
核心步驟包括:
使用curl_share_init()創建一個共享對象。
使用curl_share_setopt()設置共享的內容(如CURLSHOPT_SHARE)。
使用curl_setopt($ch, CURLOPT_SHARE, $share)將共享對象附加到easy handle。
請求完成後釋放共享對象。
下面提供一個實際可運行的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";
}
?使用curl_multi_提高並發性能*:同時發起和處理多個請求,顯著減少總耗時。
?利用curl_share_節省重複開銷*:通過共享DNS緩存等資源,避免重複解析,提高整體效率。
?注意資源釋放:請求完成後,記得釋放每個easy handle、multi handle 和share handle,否則可能導致內存洩漏。
?結合curl_multi_select() :等待網絡活動,避免CPU佔用100%。
高並發接口聚合請求。
大量頁面或文件的批量抓取。
網站監控、健康檢查。
CDN或緩存預熱。
結合使用curl_multi_exec()和curl_share_init() ,不僅可以實現真正的並發,還能通過資源共享減少重複工作,讓PHP在處理高並發網絡請求時更加高效穩定。
如果你在實際應用中遇到優化瓶頸,還可以進一步結合連接池、任務調度、異常處理等手段來完善整體方案。