在使用 PHP 的 cURL 扩展进行大量 HTTP 请求时,你可能遇到一个性能瓶颈:DNS 重复解析。每次请求时,cURL 都需要解析一次域名,这会带来额外的时间开销,尤其当你对同一个域名进行多次请求时。幸运的是,PHP 提供了一个叫 的函数,可以通过共享 DNS 缓存来避免这个问题。本文将带你了解如何使用它。
curl_share_init() 是 cURL 扩展提供的一个函数,用于创建一个共享句柄(share handle)。这个共享句柄可以在多个 cURL 会话之间共享特定资源,比如 DNS 缓存、Cookie、SSL 会话等。
当我们启用共享 DNS 缓存时,多个请求只需要解析一次域名,后续请求可以直接复用结果,大大减少了网络延迟。
我们用一个简单的示例代码来讲解如何使用:
<?php
// 创建 cURL 共享句柄
$sh = curl_share_init();
// 设置共享选项,启用 DNS 共享
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
$urls = [
'https://m66.net/api/data1',
'https://m66.net/api/data2',
'https://m66.net/api/data3',
];
foreach ($urls as $url) {
$ch = curl_init();
// 设置 URL 和其他必要的选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 绑定共享句柄
curl_setopt($ch, CURLOPT_SHARE, $sh);
// 执行请求
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo '错误: ' . curl_error($ch) . PHP_EOL;
} else {
echo '响应: ' . $response . PHP_EOL;
}
// 关闭 cURL 会话
curl_close($ch);
}
// 关闭共享句柄
curl_share_close($sh);
?>
1?? 创建共享句柄
我们用 curl_share_init() 创建一个共享句柄 $sh。
2?? 设置共享资源
通过 curl_share_setopt(),我们指定共享 DNS 数据(CURL_LOCK_DATA_DNS)。
3?? 在每个 cURL 会话中绑定共享句柄
在 curl_setopt() 中,使用 CURLOPT_SHARE 将共享句柄关联到当前的 cURL 句柄 $ch。
4?? 关闭句柄
完成所有请求后,记得用 curl_share_close() 释放共享句柄。
共享句柄必须在所有请求都完成后再关闭。
如果程序中同时运行多线程或并发请求,需要小心锁定资源,防止竞争条件。
共享 Cookie、SSL 等数据时也可以用同样的方式,只需替换 CURL_LOCK_DATA_* 常量。
对于涉及大量相同域名请求的场景,比如 API 聚合、批量抓取、负载测试,避免 DNS 重复解析通常能带来 10%~30% 的性能提升,具体取决于 DNS 查询速度和服务器延迟。虽然不是每个场景都能有巨大改进,但这是一个简单、几乎无成本的优化手段。