要让 Nginx 正确代理 WebSocket 并保持长连接,需配置 proxy_set_header Upgrade $http_upgrade、Connection "upgrade",启用 proxy_http_version 1.1、proxy_buffering off、proxy_cache off,并设置 proxy_read_timeout ≥ 心跳间隔×3(如300秒)及 proxy_send_timeout 86400。

要让 Nginx 正确代理 WebSocket 并保持长连接,不能只靠 proxy_pass,关键在于用好 proxy_set_header 配合其他必要指令。核心目标是:让后端完整收到客户端的协议升级意图,并让 Nginx 主动适配长连接生命周期。
必须透传的两个协议升级头
WebSocket 握手依赖客户端发送的 Upgrade: websocket 和 Connection: Upgrade。Nginx 默认会丢弃这两个“逐跳头”(hop-by-hop headers),导致后端收不到升级信号,返回 200 而非 101,连接直接失败。
-
proxy_set_header Upgrade $http_upgrade;:用变量动态转发原始值,兼容非标准客户端(如带Upgrade: h2c的嵌入式设备) -
proxy_set_header Connection "upgrade";:注意是英文双引号包裹的字面量"upgrade",不是$http_connection(它常为keep-alive)
必须启用 HTTP/1.1 并禁用缓冲
HTTP/1.0 不支持协议升级;默认缓冲机制会攒包、延迟帧发送,造成粘包或卡顿。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
-
proxy_http_version 1.1;:强制使用 HTTP/1.1,这是 Upgrade 前提 -
proxy_buffering off;:关在具体location块内(如/ws/),避免响应帧被缓存合并 -
proxy_cache off;:WebSocket 消息不可缓存,启用会导致握手失败
超时设置要远大于心跳间隔
Nginx 默认 proxy_read_timeout 60,空闲 60 秒就主动断 TCP 连接——用户看到的是“突然掉线”,实际是 Nginx 单方面关闭。
-
proxy_read_timeout 86400;(24 小时)最稳妥;若后端有心跳,至少设为proxy_read_timeout 300;(5 分钟),且 ≥ 心跳间隔 × 3 -
proxy_send_timeout 86400;:防止后端推送大消息或延迟响应时被中断 - 别设
0:部分 Nginx 版本行为未定义,可能引发不可预测断连
补充建议:提升健壮性
真实环境中还需兼顾 IP 透传、HTTPS 兼容和流量区分:
- 加
proxy_set_header X-Real-IP $remote_addr;和X-Forwarded-For $proxy_add_x_forwarded_for;,方便后端获取真实客户端 IP - HTTPS 场景下补
proxy_set_header X-Forwarded-Proto $scheme;,避免后端误判协议生成 http 链接 - 用
map指令更安全地处理 Connection 头:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
然后写proxy_set_header Connection $connection_upgrade;,既支持 WebSocket 又不破坏普通 HTTP 请求

















