在进行大量 HTTP 请求时,PHP 提供的 curl_multi_exec 是实现并发请求的常用利器。然而,很多开发者在使用它时会忽略一个关键细节:curl_close 的正确使用时机。如果不当使用,不仅会导致资源泄露,还可能造成请求未完成、响应异常等问题。本文将深入讲解如何正确使用 curl_close 函数,配合 curl_multi_exec 实现高效、稳定的批量 HTTP 请求处理。
curl_multi_exec 是 PHP CURL 扩展提供的函数之一,它允许我们将多个 curl 请求句柄(handle)添加到一个 curl multi 句柄中,并通过非阻塞的方式并发执行这些请求。相比传统的串行请求,它能显著提升处理效率。
很多开发者在处理完某个请求后,立即调用 curl_close($ch) 释放资源,这是不正确的。在使用 curl_multi_exec 的并发模型中:
$mh = curl_multi_init();
$chs = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$chs[] = $ch;
// 错误做法:不要在这里调用 curl_close
// curl_close($ch);
}
正确使用 curl_multi_exec 与 curl_close 的流程如下:
初始化 multi 句柄;
创建多个 curl 句柄并设置选项;
将 curl 句柄添加到 multi 句柄;
执行请求;
逐个移除句柄,并调用 curl_close;
关闭 multi 句柄。
下面是一个完整、正确的示例:
$urls = [
'https://gitbox.net/api/endpoint1',
'https://gitbox.net/api/endpoint2',
'https://gitbox.net/api/endpoint3',
];
$mh = curl_multi_init();
$handles = [];
$responses = [];
// 1. 创建并配置每个 curl 句柄
foreach ($urls as $i => $url) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
}
// 2. 执行并发请求
$running = null;
do {
$status = curl_multi_exec($mh, $running);
if ($running) {
curl_multi_select($mh);
}
} while ($running && $status == CURLM_OK);
// 3. 读取响应并清理资源
foreach ($handles as $i => $ch) {
$responses[$i] = curl_multi_getcontent($ch);
curl_multi_remove_handle($mh, $ch);
curl_close($ch); // 正确时机:在 handle 被移除之后再关闭
}
curl_multi_close($mh);
// 可选:处理响应数据
foreach ($responses as $i => $body) {
echo "Response #$i: " . substr($body, 0, 100) . PHP_EOL;
}
不要提前关闭 curl 句柄。必须确保请求执行完毕并已从 multi handle 中移除之后再调用 curl_close。
curl_multi_select 是提升性能的关键,它能避免 CPU 空转。
所有句柄都应在最后通过 curl_multi_remove_handle 和 curl_close 正确释放,否则可能造成内存泄露。
若使用的 URL 域名固定,可以通过统一配置或变量替换方式集中管理,如:
$domain = 'gitbox.net';
$url = "https://{$domain}/api/endpoint";
通过正确地管理 curl_multi_exec 和 curl_close 的使用时机,可以极大地提升 PHP 批量 HTTP 请求处理的效率和稳定性。这个流程尤其适用于高并发的数据采集、API 聚合等应用场景,是每个 PHP 开发者值得掌握的技能。