本文目录导读:

- 核心原则
- 场景一:通用 TCP Keep-Alive(系统/内核级)
- 场景二:HTTP/1.1 Keep-Alive(应用层最常接触)
- 场景三:HTTP/2 & HTTP/3
- 场景四:WebSocket(长连接典型)
- 场景五:数据库连接池(如 HikariCP / JDBC)
- 场景六:消息队列 / RPC 框架(如 gRPC、Kafka)
- 如何选择数值?
- 总结建议
长连接空闲超时的设置方法,取决于你使用的是客户端还是服务器端,以及具体的协议(如 TCP、HTTP/2、WebSocket)或框架。
下面分场景说明最常用的设置方法:
核心原则
- 服务器端:通常设置一个超时时间,如果连接在指定时间内没有数据传输,则主动断开。
- 客户端:通常设置一个比服务器略短的超时时间,或者启用 TCP Keep-Alive,以便及时检测到服务器断开的无效连接。
通用 TCP Keep-Alive(系统/内核级)
这是最底层的保活机制,操作系统负责探测,如果连接空闲,会发送探测包。
-
Linux 系统(修改
/etc/sysctl.conf或使用sysctl):# 开启 TCP Keep-Alive net.ipv4.tcp_keepalive_time = 7200 # 空闲 7200 秒(2小时)后开始探测 net.ipv4.tcp_keepalive_intvl = 75 # 每次探测间隔 75 秒 net.ipv4.tcp_keepalive_probes = 9 # 探测 9 次无响应则断开
-
Windows 系统: 通过注册表
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters修改KeepAliveTime、KeepAliveInterval等。 (注:系统参数影响所有应用,一般不推荐修改,建议应用层自己处理)
HTTP/1.1 Keep-Alive(应用层最常接触)
这是 Web 服务中最常见的场景,服务器处理完请求后不立即关闭 TCP 连接,等待下一个请求。
-
Nginx 服务器(http 或 server 块):
# 设置长连接空闲超时(秒) keepalive_timeout 65; # 客户端最大请求数(达到后无论是否超时都会断开) keepalive_requests 1000;
-
Apache 服务器:
# 关闭 HTTP/1.0 的 Keep-Alive,并设置超时 KeepAlive On KeepAliveTimeout 5 # 单位是秒,通常设为 5-15 秒 MaxKeepAliveRequests 100
-
反向代理(Nginx 连接后端):
upstream backend { server 127.0.0.1:8080; keepalive 32; # 连接池大小 } location / { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_read_timeout 60s; # 空闲后代理等待后端响应的超时 proxy_send_timeout 60s; # 空闲后代理发送数据的超时 }
HTTP/2 & HTTP/3
HTTP/2 使用多路复用复用同一个 TCP 连接,其空闲超时通常由服务器或负载均衡器控制,没有标准的 HTTP 头,常见的实现中,ETW(如 HAProxy、Envoy)会内置超时检测,超过一定时间没有帧传输即断开。
- 通用设置思路:很多 Web 服务器将其与 HTTP/1.1 的
keepalive_timeout分开或共享配置,例如在 Envoy(代理) 中:http_filters: - name: envoy.filters.http.router idle_timeout: 60s # 连接空闲 60 秒后关闭
WebSocket(长连接典型)
WebSocket 是典型的全双工长连接,需要主动心跳机制而不是依赖 TCP 超时。
-
服务器端(Node.js + ws 库):
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080, // 设置空闲超时(毫秒),超时无消息则断开 timeout: 30000, // 30秒无任何消息则断开 }); -
客户端(浏览器原生): 浏览器不支持直接设置空闲超时,需要应用层自己实现心跳检测:定时发送
ping消息,服务器回复pong,如果一段时间内没收到回应则主动关闭。
数据库连接池(如 HikariCP / JDBC)
这里的“空闲超时”指池中空闲连接的最大存活时间。
-
Java(Spring Boot + HikariCP):
# application.yml spring.datasource.hikari.maximum-pool-size=10 spring.datasource.hikari.minimum-idle=5 # 连接在池中空闲超过该时间(毫秒)则会被移出池 spring.datasource.hikari.idle-timeout=300000 # 5分钟 # 连接最大存活时间(即使它没有空闲) spring.datasource.hikari.max-lifetime=1800000 # 30分钟
-
Python (SQLAlchemy):
from sqlalchemy import create_engine engine = create_engine( "mysql+pymysql://user:pass@host/db", pool_size=5, max_overflow=2, pool_recycle=3600 # 连接在池中空闲超过1小时则回收重建 )
消息队列 / RPC 框架(如 gRPC、Kafka)
-
gRPC:基于 HTTP/2,其空闲超时可以通过 Channel 参数设置:
ManagedChannel channel = ManagedChannelBuilder.forAddress("host", port) .keepAliveTime(30, TimeUnit.SECONDS) // 30秒无流量则发送 Keep-Alive HTTP2 PING .keepAliveTimeout(5, TimeUnit.SECONDS) // PING 超时 .idleTimeout(60, TimeUnit.SECONDS) // 连接空闲60秒后进入空闲状态(可被重新激活) .usePlaintext() .build(); -
Nginx / HAProxy 连接上游服务器(常用):
upstream backend { server 127.0.0.1:8080; keepalive 32; keepalive_timeout 60s; # Nginx 1.18+ 支持 keepalive_requests 100; }HAProxy 中:
defaults timeout server 30s # 等待后端响应的超时(包含空闲超时) timeout client 30s # 等待客户端发送数据的超时 timeout http-keep-alive 10s # HTTP Keep-Alive 空闲超时
如何选择数值?
| 场景 | 推荐值 | 原因 |
|---|---|---|
| HTTP API 服务器 | 10 - 60 秒 | 用户操作间隙通常很短,过长浪费资源。 |
| WebSocket 游戏/聊天 | 30秒 - 2分钟 | 客户端本身有心跳,防止僵尸连接。 |
| 数据库连接池 | 5 - 30 分钟 | 数据库通常有服务器端超时(通常是 8 小时),池连接应小于此值避免断连。 |
| TCP 系统级 | 2 小时(默认) | 通常不动,除非你有明确的 NAT 网关超时限制(如 AWS ELB 350 秒)。 |
| 反向代理连接后端 | 与上游服务器设置的超时一致或略长 | 避免代理比服务早断开连接,导致客户端收到 504。 |
总结建议
- 如果你在开发 Web 应用:主要配置 Web 服务器(Nginx/Apache)的
keepalive_timeout。 - 如果你在开发长连接应用(Socket/WebSocket):自己实现应用层心跳,同时设置底层的 TCP Keep-Alive 作为兜底。
- 如果你在调优数据库连接池:设置
idle-timeout和max-lifetime,确保它们小于数据库的wait_timeout值。
实际调优时,可以先用一个比较保守的值(如 60 秒),然后观察连接复用率和资源占用再调整。
标签: 长连接空闲超时