websocket代理在nginx中需显式配置才能启用,核心是识别并透传upgrade请求头、设置http/1.1、正确处理connection头,握手后nginx仅作透明tcp通道,不解析帧、不缓存、不超时中断。

WebSocket 代理在 Nginx 中不是“自动开启”的功能,而是依赖特定的 HTTP 升级机制和头字段透传来完成连接升级与长连接维持。整个消息流转过程本质是:客户端发起 Upgrade 请求 → Nginx 检查并透传关键头 → 后端服务完成 WebSocket 握手 → Nginx 在后续帧传输中保持 TCP 连接不关闭、不做缓存、不拆包。
WebSocket 升级请求如何被 Nginx 识别并转发
Nginx 默认不处理 Upgrade 请求,必须显式配置支持。关键在于识别 Connection: Upgrade 和 Upgrade: websocket 这两个头字段。Nginx 仅当同时满足以下条件时,才将请求视为 WebSocket 升级请求并启用代理升级模式:
- 请求方法为
GET -
Connection头包含Upgrade(大小写不敏感) -
Upgrade头值为websocket(也大小写不敏感)
一旦匹配,Nginx 不会将该请求当作普通 HTTP 转发,而是进入“升级代理”流程:保留原始 Connection 和 Upgrade 头,并添加 Connection: upgrade(注意这里是小写 upgrade),确保后端能正确响应 101 Switching Protocols。
关键 Header 必须透传,否则握手失败
WebSocket 握手依赖多个 HTTP 头字段协同完成,Nginx 默认会过滤或重写部分头,因此需显式配置透传。最常遗漏的是:
-
Upgrade和Connection:必须用proxy_set_header显式设置,不能依赖默认值 -
Sec-WebSocket-Key和Sec-WebSocket-Version:客户端生成,用于服务端生成响应密钥,必须原样传递 -
Host:建议保留原始 Host,避免后端路由出错,可用proxy_set_header Host $host;
特别注意:proxy_http_version 1.1 是强制要求,因为 HTTP/1.0 不支持 Upgrade 机制;而 proxy_set_header Connection '' 的写法是错误的——它会清空 Connection 头,导致升级失败。正确做法是条件性透传,例如:proxy_set_header Connection $connection_upgrade;,配合 map 指令动态赋值。
Nginx 不参与 WebSocket 帧解析,只做透明通道
握手成功(返回 101 状态码)后,TCP 连接升级为 WebSocket 连接。此后所有数据(文本帧、二进制帧、ping/pong、close 帧)均以二进制流形式在客户端与后端之间双向传输。Nginx 在此阶段:
- 不解析帧结构,不校验 opcode 或 masking key
- 不缓冲、不压缩、不重写 payload
- 不主动发送 ping/pong,但会透传双方的控制帧
- 依赖操作系统 TCP 栈维持连接,超时由
proxy_read_timeout和proxy_send_timeout控制(默认 60s,建议设为 0 或较大值,如 3600)
这意味着只要 TCP 连接未断开、后端未关闭、Nginx 未因超时或错误中断连接,消息就能持续双向流转。Nginx 此时角色接近于一个“有状态的 TCP 反向代理”,而非传统 HTTP 代理。
常见中断原因及排查要点
WebSocket 连接意外断开,往往不是协议问题,而是 Nginx 配置或网络层限制所致:
-
超时中断:
proxy_read_timeout触发时,Nginx 主动关闭连接。若后端长时间无数据,需设为 0(永不超时)或足够大 -
缓冲区限制:
proxy_buffering off;必须关闭,否则 Nginx 可能缓存帧并延迟转发,破坏实时性 - SSL 层干扰:若使用 HTTPS → WSS,需确认 SSL 配置支持 ALPN(尤其在较老 OpenSSL 版本中),且证书有效
- 负载均衡粘滞缺失:多后端实例时,若连接被调度到不同节点,而 session 未共享,可能导致认证失败或状态丢失
验证是否生效,可抓包观察:客户端发出 GET + Upgrade 头 → Nginx 转发相同头 → 后端返回 101 → 后续数据为纯 WebSocket 帧(无 HTTP 头)。只要这个链路完整,消息流转就已建立。











