nginx 不生成、不响应 ping/pong,仅透传心跳、维持连接、避免缓冲截断;核心配置是透传upgrade/connection头、调大proxy_read_timeout等超时值、关闭proxy_buffering与proxy_cache。

Nginx 本身不生成、不响应、也不干预 WebSocket 的心跳(Ping/Pong 帧),它的作用是**透传心跳、维持连接不被误杀、避免帧流被缓冲或截断**。真正的心跳检测必须由前后端协同完成,Nginx 只是关键的“保活通道”。配置核心就三件事:升级头透传、超时调大、缓冲关掉。
确保 WebSocket 握手成功(升级头不能丢)
握手失败,心跳根本无从谈起。Nginx 默认会丢弃 Upgrade 和 Connection 这两个逐跳头,必须显式放行:
- proxy_http_version 1.1; —— HTTP/1.0 不支持协议升级,缺了这句会静默降级
- proxy_set_header Upgrade $http_upgrade; —— 用变量转发客户端原始值(如 websocket、h2c),不能硬写 "websocket"
- proxy_set_header Connection "upgrade"; —— 必须是带英文双引号的字面量 upgrade,不是 $http_connection(它常为 keep-alive)
这三行必须放在 location 块内(比如 location /ws/ { ... }),server 或 http 块顶层写无效。
延长超时时间,防止 Nginx 主动断连
WebSocket 是空闲长连接,Nginx 默认 proxy_read_timeout 60s:只要后端 60 秒没向客户端发数据,它就直接 FIN 断开——前端看不到错误,只看到“突然掉线”。解决方法是设为远大于心跳间隔:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- proxy_read_timeout 86400; —— 推荐设为 24 小时(86400 秒),覆盖任意业务场景
- proxy_send_timeout 86400; —— 防止后端推送大消息或响应慢时被中断
- keepalive_timeout 86400; —— 保持客户端到 Nginx 的 TCP 连接存活,与上游对齐更稳妥
注意:proxy_read_timeout 是最关键的,它控制 Nginx 等待后端数据的时间;keepalive_timeout 对 WebSocket 有效,别信“它没用”这种过时说法。
关闭缓冲与干扰机制,保证心跳帧实时透传
WebSocket 数据是连续帧流(TEXT/BINARY/PING/PONG),Nginx 默认缓冲和 Nagle 算法会导致粘包、延迟甚至丢帧:
- proxy_buffering off; —— 关在 location 块里,禁用响应缓冲,避免帧被攒包
- proxy_cache off; —— 显式禁用缓存,否则 Upgrade 请求可能被缓存命中返回 200
- tcp_nodelay on; —— 绕过 Nagle 算法,小帧(如光标移动、VAD 触发)立即送达
- gzip off; 和 proxy_set_header Accept-Encoding ""; —— 避免压缩干扰二进制帧
不要用 sub_filter、proxy_redirect 或任何可能改写响应体的操作,它们会破坏 Ping/Pong 帧结构。
验证心跳是否真正穿透(不能只看 Nginx 日志)
Nginx 日志无法确认 Ping/Pong 是否透传成功,需结合后端日志与抓包:
- 在后端服务记录收到 Ping 和发出 Pong 的时间戳,对比客户端发送时间,排查延迟或丢帧
- 用
tcpdump -i any port 8080 -w ws.pcap抓 Nginx 与后端之间流量,Wireshark 过滤websocket.opcode == 9 or websocket.opcode == 10,确认 Ping/Pong 是否到达 upstream - 检查 Nginx error log 中是否有
upstream prematurely closed connection,这往往意味着上游提前断连或超时配置不匹配










