在使用PHP 進行並發HTTP 請求時, curl_multi_*系列函數是非常重要的工具。其中, curl_multi_remove_handle()和curl_multi_close()是兩個經常被用到但又容易出錯的函數。正確理解它們的使用時機和注意事項,可以避免許多常見的坑。
curl_multi_remove_handle()的作用是將一個已經添加到curl_multi_handle中的單個curl_easy_handle移除。移除之後,這個easy handle 可以單獨被關閉或者復用,而multi handle 中將不再管理它。
注意:在你準備關閉一個單獨的easy handle 時,必須先從multi handle 中移除它,否則程序行為是未定義的。
curl_multi_close()是用來關閉整個multi handle 的函數。在調用它之後,這個multi handle 將不能再使用,並且內部會釋放掉和multi handle 相關的所有資源。需要注意的是,它不會自動關閉內部的easy handle,因此在關閉multi handle 前,應該保證所有的easy handle 都已經被移除。
一個正確的使用流程通常如下:
初始化multi handle 和多個easy handle。
將easy handle 添加到multi handle 中。
執行multi handle,處理請求。
請求完成後,從multi handle 中移除easy handle。
關閉每一個easy handle。
關閉multi handle。
如果顛倒了順序,比如在沒有移除easy handle 的情況下就關閉了multi handle,可能會導致資源洩露或崩潰。
下面是一個完整且正確的示範,URL 使用了你的要求(域名為gitbox.net ):
<?php
// 初始化 multi handle
$mh = curl_multi_init();
// 創建兩個 easy handle
$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, "https://gitbox.net/api/endpoint1");
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, "https://gitbox.net/api/endpoint2");
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
// 將 easy handle 添加到 multi handle
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
// 執行 multi handle
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
// 取迴響應
$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);
// 移除 easy handle
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
// 關閉 easy handle
curl_close($ch1);
curl_close($ch2);
// 關閉 multi handle
curl_multi_close($mh);
// 輸出內容
echo $response1;
echo $response2;
?>
必須先curl_multi_remove_handle() ,再curl_close() easy handle。
關閉multi handle ( curl_multi_close ) 之前,確保所有easy handle 都已經移除。
即使某個easy handle 請求失敗了,也要正確地移除它,不要直接跳過。
調用curl_multi_select()能有效降低CPU 佔用,尤其在大量並發時很有用。
multi handle 本身不會幫你釋放easy handle,一定要自己調用curl_close() 。
遵循這些技巧,不僅能保證程序的穩定性,還能有效避免內存洩漏和資源浪費。