Nginx子路径WebSocket反向代理必须显式配置四要素:proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade"、关闭缓冲并调大超时;否则握手失败或连接中断。

Linux 下用 Nginx 配置子路径(如 /ws/、/api/socket)的 WebSocket 反向代理,关键不是“能不能”,而是“必须显式满足协议握手条件”。默认配置下,Nginx 会静默丢掉 WebSocket 升级所需的关键头,导致前端报 WebSocket handshake error 或卡在 pending 状态。
子路径代理的核心配置项
以 location /ws/ 为例,以下四点缺一不可:
-
启用 HTTP/1.1:WebSocket 握手基于 HTTP/1.1,必须写
proxy_http_version 1.1; -
透传 Upgrade 头:用
proxy_set_header Upgrade $http_upgrade;,让客户端带的Upgrade: websocket原样转发 -
固定设置 Connection 头:必须写
proxy_set_header Connection "upgrade";(不是变量,不是$http_connection) -
关闭缓冲 + 调大超时:WebSocket 是长连接,需设
proxy_buffering off;、proxy_read_timeout 86400;、proxy_send_timeout 86400;
完整子路径配置示例
假设后端 WebSocket 服务运行在 127.0.0.1:3000,你想通过 https://example.com/ws/ 访问:
location /ws/ {
proxy_pass http://127.0.0.1:3000/; # 注意末尾斜杠,用于路径剥离
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
<pre class="brush:php;toolbar:false;">proxy_buffering off;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_connect_timeout 30;}
说明:proxy_pass 后加斜杠 /,能自动把请求路径 /ws/chat 改写为 /chat 再发给后端,避免后端收到带 /ws/ 前缀的路径。
HTTPS 子路径下必须加 WSS 支持
如果走 HTTPS(即前端用 wss://),Nginx 必须正确传递协议信息,否则后端可能误判为非安全连接:
- 确保
server块监听443 ssl,并已配置有效证书 - 在
location中保留proxy_set_header X-Forwarded-Proto $scheme; - 后端服务需识别
X-Forwarded-Proto: https并据此启用 WSS 兼容逻辑(如 Node.js 的ws库需配合https.Server或检查 header)
常见踩坑点
这些错误会导致子路径 WebSocket 表面能连上,但几秒后断开或根本无法握手:
- 漏写
proxy_http_version 1.1→ Nginx 降级为 HTTP/1.0,不支持Upgrade - 写成
proxy_set_header Connection $http_connection→ 客户端发来的是Connection: Upgrade, keep-alive,Nginx 默认只留keep-alive,升级失败 - 没关
proxy_buffering→ 消息被缓存,出现延迟、粘包,实时性崩塌 -
proxy_read_timeout仍用默认 60 秒 → 空闲连接被强制关闭,心跳失效


















