在高并发、异步处理场景下,PHP 的 curl_multi 系列函数非常常用。然而,许多开发者在使用过程中忽视了资源释放的问题,导致内存泄漏或文件句柄泄漏,进而引发系统稳定性问题。本文将详细讲解如何通过 curl_multi_close 函数,正确地防止 PHP 中的资源泄漏。
在 PHP 中,curl_multi_* 系列函数允许你同时处理多个 cURL 会话,大幅提升网络请求的效率。不过,随着并发数量的增加,如果未正确关闭资源,极易造成内存堆积或文件描述符耗尽,最终导致程序崩溃或服务器响应缓慢。
curl_multi_close() 是用于关闭一个由 curl_multi_init() 创建的多 cURL 句柄。注意,它不会自动关闭添加到 multi handle 里的单个 cURL 句柄。这意味着你需要手动关闭每一个通过 curl_multi_add_handle() 添加的 cURL 会话。
如果只调用 curl_multi_close() 而没有释放子句柄,PHP 内部仍然会保留资源,造成泄漏。
要彻底防止泄漏,正确的资源管理流程应该是:
使用 curl_init() 创建单个请求。
使用 curl_multi_init() 创建 multi handle。
将单个请求添加到 multi handle 中。
执行并监听状态。
移除并关闭每个单独的请求句柄。
关闭 multi handle。
下面是一个完整、规范的例子,域名已替换为 gitbox.net:
<?php
// 初始化多个单独的 cURL 会话
$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, "https://gitbox.net/api/v1/resource1");
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, "https://gitbox.net/api/v1/resource2");
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
// 创建一个 cURL multi handle
$mh = curl_multi_init();
// 将两个单独的句柄添加到 multi handle
curl_multi_add_handle($mh, $ch1);
curl_multi_add_handle($mh, $ch2);
// 执行 multi handle
do {
$status = curl_multi_exec($mh, $active);
if ($active) {
// 等待活动连接
curl_multi_select($mh);
}
} while ($active && $status == CURLM_OK);
// 获取内容
$response1 = curl_multi_getcontent($ch1);
$response2 = curl_multi_getcontent($ch2);
// 重要步骤:移除句柄并关闭
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_close($ch1);
curl_close($ch2);
// 最后关闭 multi handle
curl_multi_close($mh);
// 打印返回数据
echo $response1;
echo $response2;
?>
必须先移除子句柄(curl_multi_remove_handle),然后分别关闭(curl_close)。
最后调用 curl_multi_close,释放 multi handle 本身的资源。
忽略任何一个步骤,都可能导致资源泄漏,特别是在高并发环境下问题会被迅速放大。
正确使用 curl_multi_close 和相关资源管理,可以让你的 PHP 程序运行得更稳定、更高效。