nginx代理websocket断连主因是三行关键配置缺失或错误:必须在location块中同时设置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade",并配置proxy_read_timeout和proxy_send_timeout≥86400。

WebSocket 在 Nginx 后面直接断连、返回 502/504,或者浏览器控制台显示 net::ERR_CONNECTION_REFUSED,基本就是三行关键 header 没配对,或 proxy_read_timeout 太小被主动踢掉。
proxy_http_version 1.1 和两个 upgrade header 必须同时存在
Nginx 默认用 HTTP/1.0 转发请求,后端收不到 Upgrade: websocket 头,握手就失败——不是 101,而是 200 或 502。
-
proxy_http_version 1.1:强制走 HTTP/1.1,这是协议升级的前提 -
proxy_set_header Upgrade $http_upgrade:把客户端带的Upgrade头原样传下去(值通常是websocket) -
proxy_set_header Connection "upgrade":注意是字符串"upgrade",不是$http_connection,也不是"keep-alive" - 这三行必须写在
location块里,不能只放在server或http块顶层 - 顺序无关,但缺一不可;
Connection的值必须是双引号包裹的"upgrade",写成upgrade(无引号)在某些 Nginx 版本会静默失效
proxy_read_timeout 必须设大,且要同步设 proxy_send_timeout
WebSocket 是长连接,没有请求-响应周期。Nginx 默认 proxy_read_timeout 60,意味着后端 60 秒没发数据,Nginx 就直接断 TCP 连接——用户看到的就是“突然掉线”“反复重连”。
- 建议设为
proxy_read_timeout 86400(24 小时),或至少 ≥ 客户端心跳间隔 × 3 -
proxy_send_timeout 86400也要同步设置,防止后端推送延迟触发断连 -
keepalive_timeout对 WebSocket 无效,不用动它 - 别信“设成 0 就永不超时”的说法:
proxy_read_timeout 0在部分 Nginx 版本中会导致未定义行为,稳妥起见用大整数
wss:// 需要 listen 443 ssl,且证书域名必须匹配
前端用 wss://your.com/ws,但 Nginx 配置里只有 listen 80,连接会直接被拒绝,Network 面板显示 net::ERR_CONNECTION_REFUSED。
-
server块必须监听443 ssl,例如:listen 443 ssl http2; - SSL 证书路径要正确,
ssl_certificate和ssl_certificate_key指向有效文件 - 证书绑定的域名必须和前端访问的域名一致,否则 TLS 握手失败,根本到不了 HTTP 升级阶段
- 后端服务本身不需要处理 HTTPS,Nginx 终止 SSL 后以 HTTP/1.1 转发给它即可
用 curl 测试是否真正生效
别只看页面连得上,要用命令验证底层握手是否成功。
- 运行:
curl -i -k -H "Connection: upgrade" -H "Upgrade: websocket" https://your.com/ws - 期望响应头中必须包含:
HTTP/2 101或HTTP/1.1 101+Upgrade: websocket+Connection: upgrade - 如果返回 200、301、404 或压根连不上,说明配置没生效或 SSL 层卡住
-
-k是跳过证书校验,仅用于测试;生产环境务必用有效证书
最容易被忽略的是:这三个 header 必须共存于同一个 location 块内,且 proxy_read_timeout 的单位是秒(不是 s 后缀,Nginx 1.19+ 才支持带单位写法,旧版写纯数字更稳)。











