在 PHP 中,cURL 是一个强大的库,用于执行网络请求,如访问 REST API 或抓取网页。处理单个 cURL 请求时,使用 curl_init() 初始化句柄,curl_exec() 执行请求,最后通过 curl_close() 释放资源是标准流程。但在处理多个并发请求,特别是使用 curl_multi_* 系列函数时,正确关闭和清理资源显得尤为重要。否则可能导致内存泄漏或网络连接问题。
在单个请求中,典型代码如下:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://gitbox.net/api/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch); // 正确释放资源
这里,curl_close($ch) 是必须的。它会关闭由 curl_init() 创建的 cURL 句柄,并释放相关资源。
对于需要同时发起多个请求的场景,PHP 提供了 curl_multi_* 接口。示例如下:
$urls = [
'https://gitbox.net/api/one',
'https://gitbox.net/api/two',
'https://gitbox.net/api/three',
];
$multiHandle = curl_multi_init();
$curlHandles = [];
foreach ($urls as $url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($multiHandle, $ch);
$curlHandles[] = $ch;
}
// 执行所有请求
$running = null;
do {
curl_multi_exec($multiHandle, $running);
curl_multi_select($multiHandle);
} while ($running > 0);
// 获取结果
$responses = [];
foreach ($curlHandles as $ch) {
$responses[] = curl_multi_getcontent($ch);
}
此时,如果你没有执行下一步的 curl_multi_remove_handle 和 curl_close,就会出现资源未释放的问题。
在执行完所有请求并获取响应后,必须对每个句柄进行清理:
foreach ($curlHandles as $ch) {
curl_multi_remove_handle($multiHandle, $ch); // 从 multi handle 中移除
curl_close($ch); // 关闭单个 cURL 句柄,释放资源
}
curl_multi_close($multiHandle); // 最后关闭 multi handle
这是确保所有资源都得到释放的关键步骤。仅关闭 curl_multi_close() 而不逐个调用 curl_close() 是不够的。
始终显式释放:无论是单个还是多个请求,始终记得用 curl_close()。
使用 try-finally 或 error handling:处理过程中可能会有异常,建议使用 try-finally 结构确保句柄最终被释放。
监控内存和连接数:在高并发环境中,未释放的 cURL 句柄会迅速导致资源耗尽。
封装请求逻辑:建议封装成函数或类,在内部处理资源释放,避免遗漏。
curl_close() 在 PHP 中并非可有可无,尤其是在多个请求场景下。正确使用 curl_multi_remove_handle() 和 curl_close(),能确保系统稳定性和性能。写完请求逻辑后,别忘了这一步:及时清理资源,就是最好的性能优化。