nginx 稳定转发 websocket 的关键是透传 upgrade 机制并禁用干扰长连接的默认行为。需配置 proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade 和 connection "upgrade",关闭 proxy_buffering,调大 proxy_read_timeout 与 proxy_send_timeout,禁用 proxy_cache_*,推荐用 map 动态设置 connection 头。

要让 Nginx 稳定转发 WebSocket 连接,核心不是堆砌配置项,而是确保协议升级不被截断、连接不被误杀。Nginx 1.3.13+ 原生支持,但默认配置完全不适用 WebSocket 场景。
必须透传协议升级头
WebSocket 握手依赖 HTTP/1.1 的 Upgrade 机制,Nginx 默认会丢弃逐跳(hop-by-hop)头,导致后端收不到升级请求,握手直接失败(前端报 “handshake error” 或状态码卡在 200)。
- proxy_http_version 1.1; —— 缺了这句,Nginx 会降级为 HTTP/1.0 转发,Upgrade 头根本无效
- proxy_set_header Upgrade $http_upgrade; —— 使用变量可兼容 WebSocket、MQTT、STOMP 等多种 upgrade 场景
-
proxy_set_header Connection "upgrade"; —— 必须是固定字符串 "upgrade",不能写
$http_connection(客户端常发Connection: Upgrade, keep-alive,Nginx 会清理掉 Upgrade,只剩 keep-alive)
关闭干扰长连接的默认行为
WebSocket 是全双工、无请求-响应模型的 TCP 长连接,Nginx 默认策略专为短连接设计,必须主动关闭或调大相关参数。
- proxy_buffering off; —— 防止后端发送的多个 TEXT/BINARY 帧被缓存合并,造成粘包或延迟
- proxy_read_timeout 86400; —— 设为 24 小时,避免空闲期(如聊天室静默)被 Nginx 主动断开(默认仅 60 秒)
- proxy_send_timeout 86400; —— 同步调大,保障后端心跳、大消息分片能完整发出
- tcp_nodelay on; —— 绕过 Nagle 算法,小帧(如实时光标、按键事件)立即送达
避开常见陷阱配置
很多看似“合理”的写法反而让连接变得不可靠,甚至静默中断。
- 不启用任何
proxy_cache_*指令 —— WebSocket 消息不可缓存,启用会导致连接直接失败 - 不加
add_header Access-Control-Allow-Origin "*"—— WebSocket 跨域由后端在 101 响应中返回 CORS 头,Nginx 只需透传;加了可能覆盖后端设置 - 不用
proxy_set_header Connection $http_connection—— 这是高频错误,本质是把升级意图悄悄抹掉了
更稳妥的 Connection 头处理方式
若想兼顾安全性与兼容性,推荐用 map 指令动态构造 Connection 值:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
然后在 location 中写:
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
这样当客户端没带 Upgrade 头(比如普通 HTTP 请求),Nginx 就不会意外建立隧道,降低安全风险。











