PHP cURL 正确启用 HTTP Keep-Alive 需显式设置 Connection: keep-alive 头、复用同一 cURL 句柄、确保服务端支持且中间件不拦截,关键在客户端配置与服务端协商一致。

PHP cURL 如何正确启用 HTTP Keep-Alive 长连接
PHP 默认的 cURL 请求是短连接,每次请求后 TCP 连接立即关闭。要复用连接、降低延迟,必须显式开启 Keep-Alive,并确保服务端也支持。关键不在“模拟”,而在「配置协商」——客户端发对头、服务端不拒绝、连接不被中间件(如 Nginx、CDN)截断。
- 必须设置
CURLOPT_HTTPHEADER包含Connection: keep-alive(虽然现代 cURL 默认加,但显式声明更稳妥) - 禁用
CURLOPT_CLOSEPOLICY(已废弃,不用管),改用CURLOPT_FORBID_REUSE设为false(默认值,但建议显式确认) - 务必关闭
CURLOPT_RETURNTRANSFER以外的干扰选项:比如不要设CURLOPT_HEADER为true,否则响应头可能干扰连接复用逻辑 - 服务端若返回
Connection: close或使用 HTTP/1.0,Keep-Alive 会失效——可用curl_getinfo($ch, CURLINFO_HTTP_VERSION)检查实际协商版本
多次 POST 复用同一个 cURL 句柄的实操要点
真正实现“长连接保持”,不是靠单次请求加 header,而是复用同一 $ch 句柄发起多个请求。cURL 内部会在满足条件时自动复用底层 socket。
- 初始化一次
curl_init(),然后循环调用curl_setopt_array()改写 URL、POST 数据等参数,再执行curl_exec() - 每次请求前可重置 POST 数据:
curl_setopt($ch, CURLOPT_POSTFIELDS, $data),但不要调用curl_close()或重新curl_init() - 注意超时设置:用
CURLOPT_TIMEOUT控制单次请求,用CURLOPT_CONNECTTIMEOUT控制建连阶段;长连接下,CURLOPT_TIMEOUT_MS更精准 - 如果某次请求后服务端主动断连(比如返回了
Connection: close),下次curl_exec()会自动重建连接——这不是 bug,是协议合规行为
常见失败场景与诊断方法
看似开了 Keep-Alive,但 Wireshark 抓包发现仍是短连接,大概率卡在这几个环节:
- 服务端 Nginx 配置了
keepalive_timeout 0;或未开启keepalive_requests,导致直接忽略客户端请求头 - PHP-FPM 使用
pm = static且pm.max_children过小,高并发下 worker 被占满,新请求被迫排队或新建连接 - cURL 启用了
CURLOPT_SSL_VERIFYPEER或CURLOPT_SSL_VERIFYHOST,证书验证失败时连接会被异常中止,日志里可能只显示 “SSL connect error” 而非明确的连接关闭 - 用
file_get_contents()+stream_context_create()模拟 POST 时,它根本不支持 Keep-Alive 复用,必须换 cURL
一个最小可行的复用示例
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Connection: keep-alive'],
CURLOPT_FORBID_REUSE => false,
CURLOPT_TIMEOUT => 5,
]);
foreach (['a=1', 'b=2', 'c=3'] as $post) {
curl_setopt($ch, CURLOPT_URL, 'https://api.example.com/endpoint');
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$res = curl_exec($ch);
// 检查是否复用:curl_getinfo($ch, CURLINFO_PRIMARY_IP) 和 CURLINFO_STARTTRANSFER_TIME 应接近
}
curl_close($ch); // 只在全部完成后关闭
注意:CURLOPT_FORBID_REUSE 设为 false 是显式允许复用,而 CURLOPT_FRESH_CONNECT 设为 true 才强制新建——别搞反。
立即学习“PHP免费学习笔记(深入)”;
Keep-Alive 不是开关,是两端协商结果;复用效果受服务端策略、网络中间件、cURL 版本(7.62+ 对 HTTP/2 复用更友好)共同影响。压测时看 CURLINFO_NUM_CONNECTS 比看代码更准。











