tcp_keepalive_time 是 Linux 内核 TCP 层保活参数,仅在连接完全空闲时触发探测,与 Nginx 的 HTTP keepalive 完全无关;真正影响 HTTP 长连接的是 keepalive_timeout、keepalive_requests 等 Nginx 应用层配置,而非内核 TCP 参数。

`tcp_keepalive_time` 是 Linux 内核的 TCP 层保活机制参数,**它和 Nginx 的 HTTP keepalive 完全无关**。很多工程师误以为调大这个值能“延长 Nginx 长连接”,结果白改一通还引发问题。下面直接说清楚该怎么做、为什么这么做。
先划重点:tcp_keepalive_time 不影响 HTTP 长连接
这个参数只在 TCP 连接**完全空闲且无任何数据收发**时才起作用——它控制的是内核多久发送一次 TCP keepalive 探针(默认 7200 秒,即 2 小时)。而 Nginx 与客户端、或 Nginx 与后端之间的 HTTP keepalive,是应用层协议行为,靠 HTTP 头 + 主动复用逻辑 实现,全程不依赖内核探针。即使你把 tcp_keepalive_time 改成 1 秒,Nginx 的长连接也不会因此提前断开;反过来,设成 24 小时,也救不了一个被 keepalive_timeout 30s 主动关闭的空闲连接。
什么情况下才需要动 tcp_keepalive_time?
仅适用于以下两类真实场景:
-
后端服务自身使用长连接但无应用层心跳:比如某些老旧 Java 客户端直连 MySQL 或 Redis,既不发 SQL/命令也不 ping,纯靠 TCP 空闲维持连接。此时若中间有防火墙或 NAT 设备(如云厂商 SLB)主动踢掉空闲连接(常见超时 5–15 分钟),而你的后端又没做重连,就可能出错。这时可将
tcp_keepalive_time调小(如 600),配合tcp_keepalive_intvl和tcp_keepalive_probes,让内核更早探测并清理死连接。 -
Nginx 作为 TCP 代理(非 HTTP):例如用 stream 模块代理 MySQL、Redis 或自定义 TCP 协议。这时没有 HTTP keepalive,只能依赖内核 TCP 保活来及时发现对端宕机。建议设置:
net.ipv4.tcp_keepalive_time = 600net.ipv4.tcp_keepalive_intvl = 60net.ipv4.tcp_keepalive_probes = 3
这样 10 分钟无数据后开始探测,每分钟发一次,3 次失败即断连。
真正该调的,是 Nginx 自己的 keepalive 参数
想提升高并发 API 场景下的连接复用率,聚焦这三组配置即可:
-
客户端侧:
keepalive_timeout 120s;(略小于客户端 SDK 设置,如 OkHttp 默认 300s);keepalive_requests 1000;(防止单连接积压太多请求) -
上游侧(最关键):
upstream { keepalive 64; keepalive_timeout 60s; keepalive_requests 500; };再配上proxy_http_version 1.1;和proxy_set_header Connection ''; -
后端服务同步适配:如 Spring Boot 的
server.tomcat.connection-timeout=75000,确保大于 Nginx 的proxy_read_timeout和upstream keepalive_timeout
验证是否有效,别看内核参数
改完 Nginx 配置后,用这些方式确认长连接真复用了:
- 在后端机器运行
ss -s | grep -i time_wait:复用率高时,TIME_WAIT 数量应稳定低位,不会随 QPS 线性上涨 - 在 Nginx 开启
error_log /var/log/nginx/debug.log debug;,搜索keepalive.*reuse,看到大量复用日志而非create connection - 用
curl -v http://your-api/连续请求几次,再执行ss -t -o | grep :8080(假设后端端口 8080),观察源端口是否复用(同一端口多次通信)











