keepalive_timeout仅影响WebSocket握手阶段的空闲等待,不控制长连接生命周期;真正决定连接持续的是proxy_read_timeout和Upgrade头透传,二者需协同配置以避免过早断连或资源滞留。

在 WebSocket 业务中,keepalive_timeout 不直接控制 WebSocket 连接的生命周期,但它会影响 Nginx 与客户端之间 HTTP 升级前的初始连接阶段,以及代理链路中空闲连接的回收行为。真正决定 WebSocket 长连接是否持续的关键是 proxy_read_timeout 和协议升级头的正确透传,而 keepalive_timeout 的取值需与之协同,避免过早中断或资源滞留。
WebSocket 连接建立与 keepalive_timeout 的作用边界
Nginx 对 WebSocket 的支持本质是 HTTP/1.1 协议升级(Upgrade: websocket),整个流程分两阶段:
-
第一阶段(HTTP 握手):客户端发送带
Upgrade: websocket和Connection: Upgrade头的 GET 请求;Nginx 此时仍按普通 HTTP 流程处理,keepalive_timeout控制该请求响应后、连接未关闭前的空闲等待时间 -
第二阶段(WebSocket 通信):握手成功后,TCP 连接转为全双工数据通道,不再走 HTTP 请求-响应模型;此时
keepalive_timeout已失效,真正起作用的是proxy_read_timeout—— 它定义了 Nginx 在无数据到达时等待多久才主动断开连接
keepalive_timeout 的合理取值策略
该参数不宜设为过长或过短,需兼顾握手稳定性与资源释放效率:
- 建议设为 5~15 秒:足够覆盖客户端发起升级请求到 Nginx 完成响应的延迟,又不会让大量已完成升级的连接继续占用连接槽位
- 必须 小于后端服务的空闲超时设置(如 Spring Boot 的
server.tomcat.connection-timeout或 Node.js 的http.Server.timeout),否则 Nginx 可能先于后端断连,引发“连接被对端关闭”错误 - 若前端使用移动端或弱网环境,可适当放宽至 20 秒,但需同步监控文件描述符使用率,防止连接堆积
与 proxy_read_timeout 的协同配置
WebSocket 消息可能长时间静默(如聊天空闲、行情订阅待推送),此时 proxy_read_timeout 才是保活核心:
- 常规业务推荐设为 300~600 秒(5~10 分钟),满足多数心跳机制间隔(如 30 秒 ping/pong)
- 金融行情、IoT 设备等强实时场景,可设为 1800 秒(30 分钟)甚至更高,但必须确保后端也配置了匹配的读超时和心跳检测逻辑
- 务必配合
map指令清除 Connection 头干扰:
map $http_upgrade $connection_upgrade { default upgrade; '' close; }
proxy_set_header Connection $connection_upgrade;
性能权衡要点
不当配置会引发两类典型问题:
-
过长的 keepalive_timeout:导致大量已完成 WebSocket 升级的连接滞留在 Nginx 连接池中,占用 worker 进程的 socket 资源和内存,高并发下易触发
too many open files - 过短的 proxy_read_timeout:客户端尚未发送 ping 帧,Nginx 就主动断连,表现为频繁重连、消息丢失;尤其在 NAT 网关或移动网络中更明显
- 实测经验:当每秒新建 WebSocket 连接数超过 500 时,
keepalive_timeout > 30s会使单 worker 进程连接数上涨 40%,而将proxy_read_timeout从 60s 提升至 600s 对内存影响不足 3%



















