在现代Web开发中,处理大量HTTP请求是常见需求,例如批量抓取接口数据、并行下载资源、检查链接状态等。传统的串行请求方式(即一个请求结束后再发起下一个)效率低下。为此,PHP提供了 curl_multi_* 系列函数来实现并发请求,而 curl_share_* 系列则可以在多个cURL句柄间共享资源(如DNS缓存),进一步优化性能。本文将介绍如何结合 curl_multi_exec() 和 curl_share_init() 来实现高效并发请求优化。
curl_multi_* 系列函数允许我们同时发送多个HTTP请求,而不是一个一个排队等候。其核心工作流程是:
初始化一个 multi handle (curl_multi_init)。
将多个 easy handle (curl_init) 加入到 multi handle。
使用 curl_multi_exec() 驱动并发请求。
使用 curl_multi_select() 等待活动句柄(避免CPU空转)。
收集结果并关闭资源。
这种方式尤其适合需要同时处理大量请求的场景,比如爬虫、接口聚合、CDN预热等。
虽然 curl_multi_* 可以并发请求,但每个 easy handle 默认是独立的,例如每个都要单独解析DNS、维护自己的cookie等。curl_share_* 系列函数允许多个 easy handle 共享某些内部资源(如DNS缓存、SSL会话、cookie等),这样可以避免重复工作,提高性能并减少内存开销。
核心步骤包括:
使用 curl_share_init() 创建一个共享对象。
使用 curl_share_setopt() 设置共享的内容(如 CURLSHOPT_SHARE)。
使用 curl_setopt($ch, CURLOPT_SHARE, $share) 将共享对象附加到 easy handle。
请求完成后释放共享对象。
下面提供一个实际可运行的PHP代码示例:
<?php
// 需要并发请求的URL列表
$urls = [
'https://m66.net/api/endpoint1',
'https://m66.net/api/endpoint2',
'https://m66.net/api/endpoint3',
'https://m66.net/api/endpoint4'
];
// 初始化 multi handle
$multiHandle = curl_multi_init();
// 创建共享对象
$shareHandle = curl_share_init();
curl_share_setopt($shareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
// 存储各个 easy handle
$curlHandles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SHARE, $shareHandle);
curl_multi_add_handle($multiHandle, $ch);
$curlHandles[$url] = $ch;
}
// 执行并发请求
$active = null;
do {
$mrc = curl_multi_exec($multiHandle, $active);
if ($mrc == CURLM_CALL_MULTI_PERFORM) {
continue;
}
curl_multi_select($multiHandle);
} while ($active && $mrc == CURLM_OK);
// 收集结果
$responses = [];
foreach ($curlHandles as $url => $ch) {
$responses[$url] = curl_multi_getcontent($ch);
curl_multi_remove_handle($multiHandle, $ch);
curl_close($ch);
}
// 关闭 multi handle 和 share handle
curl_multi_close($multiHandle);
curl_share_close($shareHandle);
// 打印结果
foreach ($responses as $url => $content) {
echo "Response from $url:\n";
echo $content . "\n\n";
}
? 使用 curl_multi_ 提高并发性能*:同时发起和处理多个请求,显著减少总耗时。
? 利用 curl_share_ 节省重复开销*:通过共享DNS缓存等资源,避免重复解析,提高整体效率。
? 注意资源释放:请求完成后,记得释放每个 easy handle、multi handle 和 share handle,否则可能导致内存泄漏。
? 结合 curl_multi_select():等待网络活动,避免CPU占用100%。
高并发接口聚合请求。
大量页面或文件的批量抓取。
网站监控、健康检查。
CDN或缓存预热。
结合使用 curl_multi_exec() 和 curl_share_init(),不仅可以实现真正的并发,还能通过资源共享减少重复工作,让PHP在处理高并发网络请求时更加高效稳定。
如果你在实际应用中遇到优化瓶颈,还可以进一步结合连接池、任务调度、异常处理等手段来完善整体方案。