根本原因是nginx默认按短连接处理长连接,需关闭proxy_buffering、设proxy_read_timeout和proxy_send_timeout为86400、透传upgrade与connection头、后端加心跳、集群启粘性会话、启用permessage-deflate压缩并改用二进制帧。

WebSocket 经 Nginx 代理后出现消息推送延迟,根本原因不是网络带宽或服务器性能不足,而是 Nginx 默认按 HTTP 短连接逻辑处理长连接,导致缓冲积压、协议升级失败或连接被误断。优化需聚焦代理配置、后端适配与连接稳定性三方面协同调整。
关键代理配置必须关闭缓冲并延长超时
Nginx 默认启用响应缓冲和短超时,是造成“消息卡顿”最直接的配置陷阱:
-
关闭 proxy_buffering:在 WebSocket location 块中明确设置
proxy_buffering off;,否则 JSON 消息会滞留在 Nginx 缓冲区,直到缓冲满或连接关闭才批量下发; -
设为极长读取超时:使用
proxy_read_timeout 86400;(24 小时)或更高值(如604800;即 7 天),防止空闲连接被 Nginx 主动关闭; -
同步设置发送超时:添加
proxy_send_timeout 86400;,避免服务端发消息中途因超时中断; -
禁用缓存与压缩干扰:确保
proxy_cache off;,且不启用gzip或其他响应压缩,避免 WebSocket 帧被截断或解析异常。
确保协议升级头完整透传
WebSocket 握手依赖两个关键请求头,缺一不可,Nginx 必须原样或显式构造传递:
-
Upgrade 头必须转发:写为
proxy_set_header Upgrade $http_upgrade;,$http_upgrade 是 Nginx 内置变量,能正确捕获客户端原始值(如websocket); -
Connection 头必须强制设为 upgrade:写为
proxy_set_header Connection "upgrade";,不能依赖客户端传入的keep-alive, upgrade等组合值; -
HTTP 版本强制为 1.1:
proxy_http_version 1.1;是前提,HTTP/1.0 不支持持久连接与升级机制。
维持连接稳定不中断
看似“无数据”的静默期常被误判为异常,实则需主动维系连接状态:
-
后端必须发送心跳帧:服务端定期(如每 25 秒)向客户端发送
ping帧,并及时响应客户端pong,确保双向活跃; -
负载均衡需开启粘性会话:若后端为多节点集群,必须启用
ip_hash或基于 cookie 的 sticky session,否则客户端重连可能落到不同节点,导致消息无法送达; - 避免防火墙或中间设备超时切断:确认云厂商 SLB、WAF 或企业防火墙未设置更短的 TCP 空闲超时(常见为 60–300 秒),必要时同步调高这些设备的 keepalive 阈值。
精简传输与后端处理路径
即使连接通畅,消息仍可能因序列化、线程模型或格式冗余拖慢端到端响应:
- 启用 permessage-deflate 压缩:在 WebSocket 客户端和服务端协商启用该扩展,对 JSON 类文本消息压缩率通常达 60%–80%,显著减少传输体积;
-
后端使用二进制帧而非字符串:客户端设置
ws.binaryType = 'arraybuffer',服务端直接发送ArrayBuffer,绕过 UTF-8 编码/解码开销; - 替换阻塞型运行时:PHP 禁用 FPM,改用 Swoole;Python 避免 Flask/Django 同步视图,采用 Uvicorn + FastAPI 异步 handler;Java Spring Boot 启用 Netty 或 Reactor 模式。











