WebSocket连不上主因是Nginx未透传Upgrade头,需配置proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade";连接秒断需调大proxy_read_timeout等超时值;实时性差需关闭proxy_buffering和启用tcp_nodelay。

为什么 WebSocket 连不上?101 响应根本没出现
根本原因是 Nginx 没参与协议升级,把 Upgrade: websocket 和 Connection: Upgrade 当成普通头直接丢弃了。后端收不到升级信号,只能返回 200 或 400,浏览器控制台显示 Handshake failed due to invalid Upgrade header。
必须在 location 块里显式配置三要素:
-
proxy_http_version 1.1:HTTP/1.0 不支持Upgrade,设成1.0必然失败 -
proxy_set_header Upgrade $http_upgrade:用变量而非固定值"websocket",兼容非标准客户端(比如某些嵌入式设备发的是Upgrade: myproto) -
proxy_set_header Connection "upgrade":注意是字符串"upgrade",不是$connection——后者为空时 Nginx 会发Connection: close,直接断连
连接建立后秒断?别只改 proxy_read_timeout
Nginx 默认 proxy_read_timeout 60,只要后端 60 秒没发数据,它就单方面关闭 TCP 连接。WebSocket 是长连接,空闲不等于无效,这个值必须按业务心跳周期来设。
关键点不止一个超时:
-
proxy_read_timeout至少设为后端心跳间隔的 2 倍(如后端每 30 秒发ping,这里至少填65;聊天类建议直接86400) -
proxy_send_timeout必须同步调大,否则大消息分片发送中途超时,客户端收不全帧 -
keepalive_timeout也要匹配,否则客户端与 Nginx 之间的 keep-alive 连接先断,导致后续请求重连握手
消息延迟或粘包?缓冲和 Nagle 算法在捣鬼
WebSocket 数据是实时流,不是攒够一包才发。Nginx 默认开启响应缓冲和 TCP Nagle 算法,会引入毫秒级不可控延迟,对协同编辑、实时游戏这类场景就是卡顿根源。
必须关掉这两项:
-
proxy_buffering off:禁用响应缓冲,避免 Nginx 缓存后端推送的帧,导致客户端“等半天才收到” -
tcp_nodelay on:绕过 Nagle 算法,小数据包立即发出,不等 ACK 或凑满 MSS
proxy_cache 和 proxy_buffer_size 完全不用配——WebSocket 不走缓存路径,设了也无效,还可能干扰。
HTTPS + wss 场景下,漏掉 Host 和 X-Forwarded-Proto 就会循环重定向
wss:// 请求经过 Nginx SSL 终止后,后端如果靠 Host 头做虚拟主机路由,或靠 X-Forwarded-Proto 判断原始协议,漏传就会出问题:生成 http 链接、跳转到错误域名、甚至无限 302。
务必加这两行:
-
proxy_set_header Host $host:尤其当后端是多租户或泛域名服务时 -
proxy_set_header X-Forwarded-Proto $scheme:让后端知道原始是https,否则 WebSocket URL 构造可能出错
另外注意:http_v2 on 可以开,但 WebSocket 升级仍依赖 proxy_http_version 1.1——HTTP/2 不支持 Upgrade 机制,这点容易被忽略。


















