要让 Nginx 稳定代理 WebSocket,关键是防止其将长连接误作短请求处理:需显式透传 Upgrade 和 Connection 头、禁用缓冲与缓存、延长超时、确保路径匹配及 HTTPS 配置正确,并通过状态码 101、curl 握手和错误日志验证。

要让 Nginx 稳定代理 WebSocket,关键不是堆配置,而是防止它把长连接当成短请求处理。默认配置下,Nginx 会主动切断空闲连接、缓存帧数据、丢弃升级头——这些行为直接导致握手失败或静默断连。
确保协议升级不被截断
WebSocket 握手依赖两个逐跳头(Upgrade 和 Connection),Nginx 默认不透传,必须显式声明:
-
启用 HTTP/1.1:加
proxy_http_version 1.1;,HTTP/1.0 不支持协议升级语义 -
透传 Upgrade 头:用
proxy_set_header Upgrade $http_upgrade;,避免硬编码为"websocket",兼容 MQTT、STOMP 等场景 -
固定 Connection 值:写
proxy_set_header Connection "upgrade";,不能用$http_connection(可能含keep-alive,掩盖升级意图)
关闭干扰长连接的默认机制
WebSocket 是全双工 TCP 连接,不是请求-响应模型,Nginx 的默认策略会破坏其行为:
-
禁用缓冲:设
proxy_buffering off;,否则后端发送的多个帧可能被合并或延迟,造成粘包或心跳丢失 -
延长读写超时:
proxy_read_timeout 86400;和proxy_send_timeout 86400;(24 小时),值应 ≥ 后端心跳间隔(如后端每 45 秒发 ping,则 timeout 至少设为 60 秒) -
禁用压缩与缓存:关掉
gzip,且绝不能启用任何proxy_cache_*指令——WebSocket 消息不可缓存,启用即导致连接失败
检查路径匹配与 HTTPS 配置
路径和加密配置出错会导致握手在 TLS 层或路由层就失败:
-
location 必须直接匹配:例如
location /ws/ { ... },避免中间rewrite改变请求头或路径 -
HTTPS 下证书需完整:wss 连接要求 Nginx server 块中配置有效证书、密钥,并启用
ssl_protocols TLSv1.2 TLSv1.3; -
HTTP/2 不支持升级:即使启用了
http_v2,也必须保留proxy_http_version 1.1;,否则升级流程中断
验证是否真正生效
配完不验证,等于没配。重点看三处:
-
浏览器 Network 面板:WebSocket 连接状态码必须是
101 Switching Protocols,不是 200 或 502 -
curl 模拟握手:运行
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://your-domain/ws/,响应头中必须同时含Upgrade: websocket和Connection: upgrade -
Nginx 错误日志:开
error_log /var/log/nginx/error.log notice;,搜索upstream prematurely closed connection或client closed connection,有则说明仍有透传或超时问题


















