You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化PHP+CURL连接时长:如何通过长连接减少TCP/SSL握手开销

嘿,这个场景我太熟悉了——每秒多次发起HTTPS请求,每次都要走TCP三次握手+SSL完整握手,性能损耗确实拉满。好在PHP的cURL完全支持连接复用,下面给你从代码到服务器配置的全套解决方案:

核心思路:复用TCP/SSL连接(Keep-Alive)

本质就是让客户端和Nginx之间保持一个长连接,多次请求复用这个连接,避免每次都重新建立连接和握手。

1. 复用同一个cURL句柄发起多次请求

这是最直接有效的方案,不要每次请求都新建curl_init(),而是复用同一个句柄,只更新每次请求需要变动的参数(比如POST数据、请求头)。

示例代码:

// 只初始化一次cURL句柄
$ch = curl_init();

// 设置通用的固定参数(只需要设置一次)
curl_setopt($ch, CURLOPT_URL, "https://your-nginx-server.com/api");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
// 显式开启TCP Keep-Alive(默认已开启,但显式设置更稳妥)
curl_setopt($ch, CURLOPT_TCP_KEEPALIVE, true);
curl_setopt($ch, CURLOPT_TCP_KEEPIDLE, 60);  // 空闲60秒后发送保活包
curl_setopt($ch, CURLOPT_TCP_KEEPINTVL, 10); // 保活包发送间隔10秒
// 开启SSL会话缓存(默认已开启,确保复用SSL会话)
curl_setopt($ch, CURLOPT_SSL_SESSIONID_CACHE, true);

// 循环发起多次POST请求
for ($i = 0; $i < 100; $i++) {
    // 每次更新动态参数:POST数据、对应请求头
    $postData = json_encode(["request_id" => $i, "payload" => "test_data"]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Content-Type: application/json",
        "Content-Length: " . strlen($postData)
    ]);

    // 执行请求
    $response = curl_exec($ch);
    // 这里处理你的响应逻辑...
}

// 所有请求完成后再关闭句柄
curl_close($ch);

关键说明:同一个cURL句柄会自动复用之前建立的TCP/SSL连接,后续请求的连接时间会接近0(可以用curl_getinfo($ch, CURLINFO_CONNECT_TIME)验证)。如果请求的域名/端口变化,cURL会新建连接,但同一域名下的所有请求都会复用长连接。

2. 用cURL多句柄(curl_multi)处理并行请求

如果需要同时发起多个并行请求,curl_multi会自动管理连接池,同一域名的请求依然会复用已有的长连接,避免重复握手。

示例代码:

// 要请求的接口(同一域名下的多个路径)
$requestList = [
    ["url" => "https://your-nginx-server.com/api/1", "data" => ["id" => 1]],
    ["url" => "https://your-nginx-server.com/api/2", "data" => ["id" => 2]],
    // 更多请求...
];

// 初始化多句柄
$mh = curl_multi_init();
$handles = [];

// 创建单个cURL句柄并加入多句柄
foreach ($requestList as $index => $req) {
    $ch = curl_init($req["url"]);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($req["data"]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
    // 开启Keep-Alive
    curl_setopt($ch, CURLOPT_TCP_KEEPALIVE, true);
    
    $handles[$index] = $ch;
    curl_multi_add_handle($mh, $ch);
}

// 执行批量请求
$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh);
} while ($running > 0);

// 处理所有响应
foreach ($handles as $index => $ch) {
    $response = curl_multi_getcontent($ch);
    // 处理响应逻辑...
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}

curl_multi_close($mh);

3. Nginx服务器端配置配合(必须!)

光客户端设置还不够,Nginx必须开启Keep-Alive支持,否则服务器会主动关闭连接,导致客户端无法复用。修改Nginx的http或对应server块配置:

http {
    # 开启Keep-Alive
    keepalive_timeout 65;        # 连接空闲65秒后自动关闭
    keepalive_requests 1000;     # 单个连接最多处理1000次请求(适合高频率场景)
    keepalive_disable none;      # 不对任何客户端禁用Keep-Alive
}

关键说明:keepalive_requests建议设置得高一些(比如1000),这样一个长连接可以处理上千次请求才会被销毁,最大化复用效率。

额外验证小技巧

你可以用curl_getinfo($ch, CURLINFO_CONNECT_TIME)查看每次请求的连接建立时间:

  • 第一次请求的连接时间通常在0.1~0.5秒左右(TCP+SSL握手)
  • 后续复用连接的请求,连接时间会接近0(比如0.001秒)
    如果后续请求的连接时间依然很高,说明连接没有被复用,检查Nginx配置或cURL参数是否正确。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:36:14