Nginx 透传 WebSocket Upgrade 需动态使用 $http_upgrade 变量、显式设置 Connection: upgrade、启用 HTTP/1.1,并配置超时与禁用缓冲和缓存。

Nginx 支持 WebSocket 的 Upgrade 协议头传递,关键不是“加一个头”,而是**完整、动态、不干预地透传客户端原始值**。默认情况下,Nginx 会丢弃 Upgrade 和 Connection 这类逐跳(hop-by-hop)头,导致后端收不到升级意图,握手直接失败(常见 400 或 502 错误)。
必须用 $http_upgrade 动态透传
客户端发起 WebSocket 握手时,Upgrade 头的值可能是 websocket、mqtt,甚至自定义协议名。硬编码会破坏兼容性:
-
错误写法:
proxy_set_header Upgrade "websocket";—— 覆盖原始值,IoT 设备或非标 SDK 可能发h2c或chat,一概被截断 -
正确写法:
proxy_set_header Upgrade $http_upgrade;—— Nginx 内置变量,自动捕获客户端真实值;若请求没带该头,变量为空,安全无副作用
必须配合 Connection: upgrade 显式设置
Upgrade: websocket 是“申请”,Connection: upgrade 才是真正触发协议切换的指令。Nginx 默认可能把 Connection 改成 close 或 keep-alive,直接中断升级链路:
-
基础写法:
proxy_set_header Connection "upgrade";—— 注意双引号包裹固定字符串"upgrade",不是变量 -
更稳妥写法:用
map指令做条件判断,兼顾普通 HTTP 流量:map $http_upgrade $connection_upgrade {<br> default upgrade;<br> '' close;<br>}然后在 location 中写:proxy_set_header Connection $connection_upgrade;
三要素必须共存且位置正确
仅设对头还不够,这三项必须同时满足,缺一不可:
-
proxy_http_version 1.1;—— HTTP/1.0 不支持 Upgrade 机制,这是前提 proxy_set_header Upgrade $http_upgrade;-
proxy_set_header Connection $connection_upgrade;(或"upgrade") - 全部配置必须放在
location块内,且紧邻proxy_pass指令下方,缩进对齐;不能写在http或server全局块里
配套设置防止连接意外中断
透传头只是第一步,WebSocket 是长连接,Nginx 默认行为极易造成“静默断连”:
-
proxy_read_timeout 86400;—— 默认 60 秒,空闲超时即断;设为 24 小时可覆盖绝大多数心跳间隔(如每 30 秒 ping/pong) -
proxy_send_timeout 86400;—— 防止服务端推送大消息或分片时被中途切断 -
proxy_buffering off;—— WebSocket 是帧流,缓冲会导致延迟、粘包甚至握手失败 - 禁用所有
proxy_cache_*指令 —— WebSocket 消息不可缓存,开了必出错


















