在 PHP 中處理多個 HTTP 請求時,串行執行會嚴重拖慢效能。利用 cURL 的多執行緒功能(curl_multi),我們可以同時發送多個請求,大幅縮短總響應時間。本文提供一個封裝良好的 MultiHttpRequest 類,並示範如何輕鬆實現併發抓取。
$urls = [
"https://www.baidu.com",
"https://www.example.com",
"https://www.google.com"
];
$multiRequest = new MultiHttpRequest($urls);
$multiRequest->start();
class MultiHttpRequest {
public $urls = [];
public $curlopt_header = 1; // 是否包含回應標頭
public $method = "GET";
public function __construct($urls = false) {
$this->urls = $urls;
}
public function set_urls($urls) {
$this->urls = $urls;
return $this;
}
public function is_return_header($bool) {
$this->curlopt_header = $bool;
return $this;
}
public function set_method($method) {
$this->method = strtoupper($method);
return $this;
}
public function start() {
if (!is_array($this->urls) || empty($this->urls)) {
return false;
}
$handles = [];
$mh = curl_multi_init();
// 初始化每個 cURL handle 並加入多執行緒管理器
foreach ($this->urls as $key => $url) {
$handles[$key] = $this->addHandle($mh, $url);
}
// 批次執行
$this->execHandles($mh);
// 取得結果並清理
foreach ($this->urls as $key => $url) {
$content = curl_multi_getcontent($handles[$key]);
echo "[$key] $url\n$content\n\n";
curl_multi_remove_handle($mh, $handles[$key]);
}
curl_multi_close($mh);
}
private function addHandle($mh, $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $this->curlopt_header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
curl_multi_add_handle($mh, $ch);
return $ch;
}
private function execHandles($mh) {
$active = null;
do {
curl_multi_exec($mh, $active);
} while ($active > 0);
}
}
實際專案中可擴展錯誤處理(檢查 curl_error())、超時控制(CURLOPT_TIMEOUT)、並發數限制(分批處理)以及回調函數處理非同步結果。善用多線程 cURL,能讓爬蟲、API 聚合、微服務呼叫等場景效能提升數倍。