http/2 不支持 websocket 升级,因协议废除 connection: upgrade 机制;nginx 需通过分离端口、子域名或 stream 模块等方式强制 websocket 走 http/1.1,并配置 proxy_http_version 1.1、upgrade 和 connection 头。

HTTP/2 本身不支持 WebSocket 协议,Nginx 在启用 HTTP/2 后,无法直接通过 h2 连接升级(upgrade)到 WebSocket。这是由 HTTP/2 协议设计决定的:它废除了 HTTP/1.1 中的 Connection: upgrade 和 Upgrade: websocket 机制,不再允许任意协议升级。因此,若 Nginx 前端监听的是 HTTP/2(如 listen 443 http2),客户端发起的 WebSocket 连接(wss://)将失败或回退为非标准行为。
WebSocket 必须走 HTTP/1.1 清单
要让 WebSocket 正常工作,Nginx 必须在处理 WebSocket 请求时使用 HTTP/1.1,常见做法是:
- 为 WebSocket 路径(如
/ws或/api/ws)单独配置一个 server 块或 location,监听在独立端口或通过 SNI 区分,并显式禁用 HTTP/2; - 或在同一 HTTPS server 中,通过
map指令识别 WebSocket 升级请求,再用if+return 302或反向代理重定向到另一个仅启用 HTTP/1.1 的 upstream; - 更稳妥的方式是:保持主站用 HTTP/2,但将 WebSocket 流量通过子域名(如
ws.example.com)分离,并为其 server 配置中移除http2参数。
Nginx 配置 WebSocket 的关键指令
无论是否涉及 HTTP/2,启用 WebSocket 反向代理必须包含以下设置:
-
proxy_http_version 1.1;— 强制使用 HTTP/1.1 与后端通信; -
proxy_set_header Upgrade $http_upgrade;— 透传 Upgrade 头; -
proxy_set_header Connection "upgrade";— 显式设置 Connection 头为 upgrade(注意带引号); -
proxy_read_timeout 86400;— 长连接超时建议设大,避免空闲断连。
如何验证是否走通 WebSocket
不要只看浏览器控制台有没有报错,需逐层确认:
- 浏览器开发者工具 Network 标签中,WebSocket 连接的 Protocol 列应显示
websocket,且状态为101 Switching Protocols; - 用
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" https://example.com/ws模拟升级请求,观察响应头是否含HTTP/1.1 101和正确 Upgrade 头; - 检查 Nginx error.log,搜索
"upstream sent no valid HTTP/1.0 header"或"client sent invalid upgrade request"等提示,通常意味着 HTTP/2 干扰或 proxy 指令缺失。
替代方案:使用边缘网关或跳过 Nginx TLS 终止
若架构允许,可考虑绕过 Nginx 的 TLS 层来保 WebSocket 全链路兼容:
- 让 Nginx 仅作 TCP 代理(stream 模块),不解析 HTTP,把
wss://流量直转给后端(如 Node.js ws server),此时 HTTP/2 不介入; - 在前端 CDN(如 Cloudflare)或专用边缘网关(如 Envoy)上统一处理 HTTP/2 和 WebSocket 分流,Nginx 退为纯 HTTP/1.1 应用代理;
- 后端服务自身启用 TLS 并直接暴露 wss,Nginx 改为基于 IP 或路径的四层转发,彻底规避七层协议冲突。










