在 PHP 中处理多个并发的 cURL 请求时,curl_multi_init() 和相关的函数(如 curl_multi_add_handle()、curl_multi_exec()、curl_multi_getcontent() 和 curl_multi_close())非常实用。尤其是在请求多个接口、抓取大量网页数据、或者构建并发 API 调用逻辑时,这套接口可以显著提升性能。
然而,在调用 curl_multi_close() 之前,我们通常需要收集和处理每个请求的返回值。不同的请求可能返回不同格式、不同状态的结果,如何高效地管理这些返回值,是开发者必须面对的问题。
本文将详细讲解如何在调用 curl_multi_close() 之前,结构化地处理多个返回值,包括:成功响应、失败信息、HTTP 状态码等。
$multiHandle = curl_multi_init();
$curlHandles = [];
$urls = [
'https://gitbox.net/api/data1',
'https://gitbox.net/api/data2',
'https://gitbox.net/api/data3',
];
// 初始化多个 cURL handle
foreach ($urls as $url) {
$ch = curl_init($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);
在执行完成之后,通常我们会遍历每个 handle 来获取内容和其他信息:
$responses = [];
foreach ($curlHandles as $ch) {
$content = curl_multi_getcontent($ch);
$error = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$responses[] = [
'content' => $content,
'error' => $error,
'http_code' => $httpCode,
];
// 释放单个 handle
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch);
}
收集完所有数据后,最后一步是关闭 multi handle:
curl_multi_close($multiHandle);
通过上面的处理,我们最终获得了一个结构清晰的 $responses 数组:
[
[
'content' => '{...}', // JSON或HTML等
'error' => '', // 如果没有错误
'http_code' => 200,
],
[
'content' => '',
'error' => 'Could not resolve host: gitbox.net',
'http_code' => 0,
],
...
]
这样就能在关闭 multi handle 之前,把每个请求的响应值按格式收集好,便于后续处理,比如日志记录、错误分析、重试策略等。
异常处理集中化:为每一个请求定义处理策略,比如 HTTP 5xx 重试、HTTP 4xx 记录警告。
数据格式预验证:尝试用 json_decode() 判断响应内容是否合法,避免后续业务逻辑崩溃。
响应映射标识:如果你要处理上百个请求,建议为每个 handle 设置自定义标识(如 URL 或 ID),方便对应响应来源。
合理使用 curl_multi_select():它能有效降低 CPU 占用,避免 curl_multi_exec 无限轮询。
在使用 curl_multi_close() 关闭资源前,务必确保你已经从每个 cURL handle 中提取了你需要的全部信息。通过结构化地收集 content、error 和 http_code,你可以高效管理大规模的并发请求,为后续的业务处理打好基础。
你是否还需要将这段代码打包成一个通用函数方便复用?