websocket心跳需nginx透传ping/pong帧并维持长连接:正确配置协议升级头、延长proxy_read_timeout等超时时间、禁用缓冲与响应重写,并通过后端日志和抓包验证透传效果。

WebSocket 连接本身不内置心跳机制,但客户端和服务端可通过 Ping/Pong 帧或自定义消息实现心跳。Nginx 作为反向代理,不主动发送或生成心跳帧,但它必须正确透传心跳帧、维持长连接,并避免因超时断连导致心跳失效。关键在于配置 Nginx 保持连接活跃、禁用代理缓冲、并透传 WebSocket 协议头。
确保 WebSocket 协议升级被正确透传
Nginx 必须允许并透传 Upgrade 和 Connection: upgrade 请求头,否则 WebSocket 握手失败,心跳无从谈起。
- 在
location块中显式添加:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; - 若缺少
proxy_http_version 1.1,Nginx 默认用 HTTP/1.0,无法支持升级;
若Connection被覆盖(如设为close),握手直接被拒绝。
延长超时时间,防止 Nginx 主动断连
Nginx 的默认超时(如 proxy_read_timeout)通常为 60 秒。若服务端心跳间隔 >60s 或网络延迟高,Nginx 可能在心跳到达前关闭空闲连接。
- 将
proxy_read_timeout设为略大于服务端最大心跳间隔(例如心跳每 45s 一次,则设为60或90); - 同时建议设置
proxy_send_timeout(默认 60s),避免客户端响应慢时被中断; -
keepalive_timeout(作用于 client–nginx 连接)也应同步调大,例如:
keepalive_timeout 75s;
禁用缓冲和重写,保证心跳帧实时透传
Nginx 若启用响应缓冲(如 proxy_buffering on)或尝试重写响应体,可能延迟甚至截断二进制的 Ping/Pong 帧,导致心跳失效。
- 强制关闭缓冲:
proxy_buffering off; - 禁用响应头重写(尤其避免修改
Content-Length或压缩):
proxy_set_header Accept-Encoding "";
gzip off; - 不要使用
sub_filter或proxy_redirect等可能干扰原始帧的操作。
验证心跳是否真正穿透 Nginx
仅靠 Nginx 日志无法确认心跳帧是否透传成功,需结合后端日志与抓包分析:
- 在后端服务记录收到的 Ping/Pong 时间戳,对比客户端发送时间,排查延迟或丢帧;
- 用
tcpdump或 Wireshark 抓取 Nginx 与后端之间的流量,过滤 WebSocket 数据帧(opcode=9/10),确认 Ping/Pong 是否到达 upstream; - 检查 Nginx error log 中是否有
upstream prematurely closed connection,这往往意味着上游提前断连或超时配置不匹配。











