要让nginx代理websocket真正稳定,核心是透传upgrade头部、合理设置超时(proxy_read_timeout需大于心跳间隔)、关闭缓冲与缓存(proxy_buffering off、proxy_cache off)、启用tcp_nodelay,并确保路径匹配与会话保持。

要让 Nginx 代理 WebSocket 连接真正稳定,核心不是堆参数,而是让每个配置项都匹配 WebSocket 的通信本质:它不是请求-响应式短连接,而是全双工、长生命周期、依赖协议升级的 TCP 通道。配置错一处,就可能握手失败、静默断连或消息乱序。
必须透传协议升级头
WebSocket 握手靠 HTTP Upgrade 机制完成,Nginx 默认会丢弃关键头部,导致后端收不到升级信号,返回 200 而非 101 —— 这是“连不上”的最常见原因。
- proxy_http_version 1.1:强制使用 HTTP/1.1,HTTP/2 不支持 Upgrade,不能替代
- proxy_set_header Upgrade $http_upgrade:用变量转发原始值(如 websocket、mqtt),别写死 "websocket"
- proxy_set_header Connection "upgrade":必须是带英文双引号的字面量 upgrade,不能用 $http_connection(它常含 keep-alive,会覆盖升级意图)
超时设置要贴合心跳节奏
Nginx 默认 proxy_read_timeout=60 秒,只要 60 秒没从后端收到数据,就会主动断开连接。而 WebSocket 空闲时只靠心跳维持,一旦心跳间隔 >60 秒,连接必然中断。
- proxy_read_timeout 设为略大于后端心跳间隔(例如后端 ping/pong 每 30 秒一次,这里至少设 60;游戏类可设 300–1800)
- proxy_send_timeout 同步调大,避免向后端推送广播消息或大帧时被中途切断
- keepalive_timeout 可设为与 proxy_read_timeout 对齐,或按后端连接空闲策略单独设定(如 Spring Boot 的 connection-timeout)
关闭干扰流式通信的默认行为
WebSocket 数据是连续帧流,Nginx 默认开启的缓冲和缓存机制会截断、合并、延迟甚至丢弃帧,尤其在协同编辑、实时游戏等场景下表现明显。
- proxy_buffering off:必须放在具体的 location 块中(如 /ws/),不能写在 http 全局块
- proxy_cache off:显式禁用,防止 Upgrade 请求被缓存命中返回 200
- tcp_nodelay on:绕过 Nagle 算法,小帧(如按键、光标移动)立即发出,降低端到端延迟
路径匹配与后端路由一致性
即使配置全对,如果请求没进到正确的 location,或负载均衡把后续帧打到不同后端,连接照样不可用。
- 用精确匹配(location = /ws)或前缀匹配(location /ws/),避免 rewrite 改写路径或 header
- 集群场景下启用会话保持:ip_hash(简单有效)、sticky cookie(需 Plus 或模块)、或后端共享状态(如 Redis 存连接映射)
- upstream 中加 keepalive 32 和基础健康检查(max_fails=3 fail_timeout=30s),减少后端单点失效影响











