Nginx 默认不支持 WebSocket 长连接,必须显式配置 proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade"、proxy_buffering off、proxy_read_timeout 86400、proxy_send_timeout 86400,且全部置于 location 块内,否则握手失败或连接秒断。

直接说结论:Nginx 默认不支持 WebSocket 长连接,不是加几行配置就能“启用”,而是必须显式绕过它对 HTTP 短连接的默认假设——否则握手失败、60 秒断连、心跳被截断,全是必然结果。
proxy_http_version 1.1 和 Upgrade 头必须同时存在
WebSocket 握手依赖 HTTP/1.1 的 Upgrade 机制,缺一不可。Nginx 默认用 HTTP/1.0 转发请求,后端收不到 Upgrade: websocket 就直接拒掉。
-
proxy_http_version 1.1;是前提,没有它,$http_upgrade变量为空,proxy_set_header Upgrade $http_upgrade;实际转发的是空值 -
proxy_set_header Upgrade $http_upgrade;必须用变量,不能硬写"websocket"——客户端可能发Upgrade: chat或其他自定义协议 -
proxy_set_header Connection "upgrade";注意是固定字符串"upgrade",不是$http_connection;Connection 是逐跳头,不能继承客户端原始值(比如keep-alive)
proxy_read_timeout 不是“可选优化”,而是保命参数
默认值 proxy_read_timeout 60; 就是 WebSocket 断连的定时炸弹。它控制 Nginx 从后端读数据的空闲等待时间,对已升级的 WebSocket 连接同样生效。
- 设为
86400(24 小时)是常见做法,但真正该设多大,取决于你后端心跳间隔——必须 ≥ 后端最大允许空闲时长 - 只调大
proxy_read_timeout不够,proxy_send_timeout也要同步设大,否则服务端发一个大消息或延迟响应时会被掐断 - 别信“设成 0 就永久连接”——Nginx 不支持 0 值,会回退到默认 60,必须填正整数
proxy_buffering off; 不是建议,是强制要求
WebSocket 数据是帧(frame)流,不是完整响应体。Nginx 若开启缓冲,会攒着帧不往下推,导致前端收不到实时消息,甚至粘包或超时重连。
-
proxy_buffering off;必须显式关闭,不能依赖“没开就是关”——默认是on - 禁用缓冲后,
proxy_buffer_size、proxy_buffers等参数失效,无需再配 - 别在 location 里加
proxy_cache相关指令——WebSocket 消息不可缓存,Nginx 遇到会直接报错或静默失败
HTTPS 下 wss:// 连接失败,大概率卡在 SSL 配置
wss 要求整个链路加密,Nginx 终止 SSL 后再代理明文 ws 到后端,但浏览器会校验 Nginx 返回的 101 响应是否来自可信 HTTPS 上下文。
- server 块必须含完整 SSL 配置:
ssl_certificate、ssl_certificate_key、ssl_protocols TLSv1.2 TLSv1.3 - 不要在 server 块里加
http_v2 on;——HTTP/2 不支持 Upgrade 机制,开了反而让 WebSocket 握手失败 - location 匹配要直给,避免 rewrite:比如用
location /ws/ { ... },别写成location /api { rewrite ^/api/ws/(.*)$ /ws/$1 break; },rewrite 会清空$http_upgrade
最容易被忽略的一点:所有这些配置必须放在 location 块里,而不是 server 或 http 块顶层。Nginx 的 proxy 指令作用域很关键,放错位置等于没写。


















