优化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
相关产品推荐
相关产品推荐

