當前位置: 首頁> 最新文章列表> curl_multi_close 與curl_multi_init 的正確順序使用

curl_multi_close 與curl_multi_init 的正確順序使用

gitbox 2025-05-12

在PHP中, cURL是一個強大且常用的網絡請求工具,而curl_multi_*系列函數允許我們。這在進行高性能接口聚合、異步請求等場景中非常有用。

然而,許多開發者在使用curl_multi_*時,常常忽略了資源的釋放環節,尤其是curl_multi_close()的使用。本文將以標準流程為主線,帶你一步步理解從curl_multi_initcurl_multi_close的完整使用方式,並輔以代碼示例說明。

一、什麼是curl_multi 系列函數?

PHP 提供的curl_multi_*系列函數是用於管理多個並發curl 句柄的工具。這與傳統的單個curl 請求不同,它允許你同時發起多個HTTP 請求,提升響應效率。

使用這些函數可以大致分為以下幾個步驟:

  1. 初始化multi 句柄: curl_multi_init()

  2. 添加多個curl 請求(easy handle): curl_multi_add_handle()

  3. 執行請求: curl_multi_exec()curl_multi_select()

  4. 獲取響應內容: curl_multi_getcontent()

  5. 移除並關閉easy handle: curl_multi_remove_handle()curl_close()

  6. 關閉multi handle: curl_multi_close()

二、標準流程講解及代碼示例

下面是一個標準的多請求流程,假設我們需要並發請求三個不同的URL:

 <?php

// 要請求的 URL 列表
$urls = [
    "https://gitbox.net/api/service1",
    "https://gitbox.net/api/service2",
    "https://gitbox.net/api/service3"
];

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

// 1. 為每個 URL 創建一個 curl easy handle 並添加到 multi handle 中
foreach ($urls as $i => $url) {
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[$i] = $ch;
}

// 2. 執行 multi 請求
$active = null;
do {
    $mrc = curl_multi_exec($multiHandle, $active);
    // 等待網絡 I/O 準備好,避免 CPU 佔用過高
    if ($mrc == CURLM_OK) {
        curl_multi_select($multiHandle);
    }
} while ($active > 0 && $mrc == CURLM_OK);

// 3. 獲取內容並清理句柄
$responses = [];
foreach ($curlHandles as $i => $ch) {
    // 獲取響應內容
    $responses[$i] = curl_multi_getcontent($ch);

    // 移除並關閉單個 handle
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}

// 4. 最後關閉 multi handle,釋放資源
curl_multi_close($multiHandle);

// 輸出結果
foreach ($responses as $index => $body) {
    echo "Response from URL #{$index}: \n";
    echo $body . "\n\n";
}

三、為什麼curl_multi_close 很重要?

雖然curl_multi_close()並不會立即銷毀easy handle(你需要先移除再關閉它們),但它負責釋放multi handle 本身佔用的底層資源。如果你忘記調用它,在長時間運行的腳本(如常駐進程)中可能導致內存洩漏或者文件描述符耗盡的問題。

總結:任何使用了curl_multi_init()的腳本,必須以curl_multi_close()結尾!

四、常見問題排查建議

  1. 請求阻塞卡住?

    • 檢查是否正確使用了curl_multi_select()

    • 確保沒有漏掉curl_setopt(..., CURLOPT_RETURNTRANSFER, true)

  2. 內存洩露或連接異常?

五、總結

在並發處理網絡請求時, curl_multi_*提供了非常高效的手段。掌握從curl_multi_init()curl_multi_close()的完整流程,能有效提高代碼性能和資源管理能力。

記住這三個“必須”:

  • 每個請求都必須添加到multi 句柄中;

  • 每個請求都必須在完成後被移除和關閉;

  • 最終必須調用curl_multi_close()來釋放multi 資源。

通過規範的流程和資源管理,你的PHP 並發請求將更加健壯和高效。