當前位置: 首頁> 最新文章列表> 如何在並發請求完成後,優雅地關閉所有CURL 會話

如何在並發請求完成後,優雅地關閉所有CURL 會話

gitbox 2025-05-12

在進行大量並發HTTP 請求時,PHP 提供的curl_multi_*系列函數是一個非常實用的工具,能讓你在一個腳本中同時發起多個請求,從而提高執行效率。其中, curl_multi_close()是整個流程中的最後一步,它負責清理curl_multi_init()初始化的資源,確保所有的CURL 句柄被妥善關閉,不留下資源洩露的隱患。本文將通過一個完整的示例,詳細講解如何在所有並發請求完成之後,優雅地關閉所有CURL 會話。

一、基礎概念回顧

在使用curl_multi_*進行並發請求時,一般的流程如下:

  1. 初始化一個curl_multi容器。

  2. 創建多個curl請求,並將其加入curl_multi容器。

  3. 使用curl_multi_exec驅動所有請求的執行。

  4. 循環檢查請求是否完成。

  5. 分別處理每一個curl請求的結果。

  6. 移除每一個單獨的curl句柄。

  7. 使用curl_multi_close()釋放資源。

二、示例代碼講解

以下是一個示例,演示如何並發請求多個URL,並在所有請求結束後優雅地關閉資源:

 <?php

// 要並發請求的 URL 列表
$urls = [
    "https://gitbox.net/api/data1",
    "https://gitbox.net/api/data2",
    "https://gitbox.net/api/data3"
];

// 初始化 curl_multi 句柄
$multiHandle = curl_multi_init();
$curlHandles = [];

// 為每一個 URL 創建一個單獨的 curl 句柄,並加入 multi 句柄
foreach ($urls as $url) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10
    ]);
    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[] = $ch;
}

// 執行所有請求
$active = null;
do {
    $mrc = curl_multi_exec($multiHandle, $active);
    // curl_multi_select 阻塞直到有活動連接
    if ($active) {
        curl_multi_select($multiHandle);
    }
} while ($active && $mrc == CURLM_OK);

// 獲取每一個請求的返回結果
foreach ($curlHandles as $ch) {
    $response = curl_multi_getcontent($ch);
    $info = curl_getinfo($ch);
    $error = curl_error($ch);

    echo "URL: " . $info['url'] . PHP_EOL;
    echo "HTTP Code: " . $info['http_code'] . PHP_EOL;
    echo "Response: " . $response . PHP_EOL;
    echo "Error: " . $error . PHP_EOL;
    echo str_repeat("-", 40) . PHP_EOL;

    // 移除並關閉句柄
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}

// 最後,關閉 multi 句柄
curl_multi_close($multiHandle);

?>

三、關於curl_multi_close 的注意事項

  • 只在所有句柄都被移除後調用:調用curl_multi_close()之前,應該先通過curl_multi_remove_handle()把所有子句柄從multi 容器中移除,再逐個調用curl_close() 。否則可能造成資源未釋放或行為不確定。

  • 不會自動關閉子句柄curl_multi_close()只會關閉multi 容器自身,並不會自動關閉內部的curl 句柄。你需要手動關閉每一個curl_init()創建的句柄。

  • 調用時機curl_multi_close()應該是你整個流程中最後執行的步驟。它的調用標誌著整個並發請求生命週期的正式結束。

四、總結

通過合理使用curl_multi_init()curl_multi_close() ,你可以在PHP 中高效地進行並發網絡請求,同時確保資源在使用完畢後被正確釋放,避免內存洩漏或連接異常。務必記住:每一個curl_init()對應一個curl_close() ,每一個curl_multi_init()對應一個curl_multi_close() ,這樣才能讓你的代碼更加健壯和可靠。