首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP cURL 多執行緒並發請求:大幅降低後端 API 回應時間

     編輯:PHP 相關知識

前言

串接多個後端 API 時,循序請求會導致總耗時等於所有 API 耗時之和。使用 curl_multi 並發請求,可將總耗時降至最慢單一 API 的耗時,顯著提升頁面載入速度。

循序請求 vs 並發請求 效能比較

循序請求(傳統寫法)

<?php
function curl_fetch($url, $timeout = 3) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_RETURNTRANSFER => 1,
    ]);
    $data = curl_exec($ch);
    $errno = curl_errno($ch);
    curl_close($ch);
    return $errno ? false : $data;
}

$urls = [
    "taobao" => "https://www.taobao.com",
    "sohu"   => "https://www.sohu.com",
    "sina"   => "https://www.sina.com.cn",
];

$start = microtime(true);
$results = [];
foreach ($urls as $key => $url) {
    $results[$key] = curl_fetch($url);
}
echo "循序耗時: " . (microtime(true) - $start) . " 秒"; // 約 0.614 秒
?>

並發請求(curl_multi)

<?php
function curl_multi_fetch(array $urls, $timeout = 2): array {
    $mh = curl_multi_init();
    $handles = [];
    $results = [];

    // 初始化所有 handle 並加入 multi handle
    foreach ($urls as $key => $url) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_HEADER => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $timeout,
        ]);
        curl_multi_add_handle($mh, $ch);
        $handles[$key] = $ch;
    }

    // 執行並發請求
    $running = null;
    do {
        $mrc = curl_multi_exec($mh, $running);
    } while ($mrc === CURLM_CALL_MULTI_PERFORM);

    while ($running && $mrc === CURLM_OK) {
        // 等待網路活動
        if (curl_multi_select($mh, 0.5) > -1) {
            do {
                $mrc = curl_multi_exec($mh, $running);
            } while ($mrc === CURLM_CALL_MULTI_PERFORM);
        }
    }

    // 收集結果
    foreach ($handles as $key => $ch) {
        if (curl_errno($ch) === 0) {
            $results[$key] = curl_multi_getcontent($ch);
        } else {
            $results[$key] = false;
            error_log("cURL error ({$key}): " . curl_error($ch));
        }
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }
    curl_multi_close($mh);
    return $results;
}

$start = microtime(true);
$results = curl_multi_fetch($urls);
echo "並發耗時: " . (microtime(true) - $start) . " 秒"; // 約 0.316 秒
?>

關鍵 cURL 多執行緒函數速查

函數用途
curl_multi_init()建立多執行緒控制代碼
curl_multi_add_handle()加入單一 cURL handle
curl_multi_exec()執行並發請求
curl_multi_select()等待任一連線有活動(可設超時)
curl_multi_getcontent()取得已完成請求的回應內容
curl_multi_info_read()讀取已完成傳輸的詳細資訊
curl_multi_remove_handle()移除 handle
curl_multi_close()關閉多執行緒控制代碼

最佳實務建議

  • 設定合理超時:CURLOPT_TIMEOUT 避免單一慢速 API 拖垮整體
  • 錯誤處理:檢查 curl_errno() 區分網路錯誤與 HTTP 錯誤碼
  • 限制並發數:大量請求時分批處理,避免耗盡檔案描述符或觸發對方限流
  • 考慮非同步替代方案:Swoole、ReactPHP、Guzzle Promise 提供更高階的非同步介面
  • 重用連線:啟用 CURLOPT_TCP_KEEPALIVE 減少握手開銷

效能提升總結

測試環境下,3 個 API 並發請求將總耗時從 0.614 秒降至 0.316 秒,效能提升約 48%。實際提升幅度取決於最慢 API 的回應時間與網路延遲。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved