Nginx 的 proxy_cache 不能缓存 WebSocket 握手后的帧数据,因其仅支持标准 HTTP 响应缓存,而 WebSocket 升级后为无状态、双向、流式 TCP 连接,无传统响应体可供缓存。

Nginx 的 proxy_cache 不能缓存 WebSocket 握手后的数据(即升级后的长连接帧数据)。
WebSocket 是基于 TCP 的全双工长连接协议,一旦完成 HTTP 升级(Upgrade: websocket),后续通信就脱离 HTTP 协议范畴,进入二进制/文本帧传输阶段。而 Nginx 的 proxy_cache 模块仅支持缓存标准 HTTP 响应(有状态码、头、体的短连接响应),它不感知、也无法截获或存储 WebSocket 连接中持续收发的帧数据。
为什么 proxy_cache 对 WebSocket 数据无效
-
proxy_cache工作在 HTTP 层,依赖请求方法(如 GET)、响应状态码(如 200)、可缓存头(如Cache-Control)等; - WebSocket 升级成功后,连接保持打开,没有传统意义上的“响应体”供缓存;
- Nginx 不解析或缓冲 WebSocket 帧(RFC 6455),它只做透明代理转发;
- 缓存机制无法处理流式、双向、无明确结束标记的数据流。
哪些环节可以“类缓存”或优化 WebSocket 性能
虽然不能缓存帧数据,但可通过以下方式降低后端压力、提升连接效率:
-
复用上游连接
启用proxy_http_version 1.1和proxy_set_header Connection '',让 Nginx 复用到后端的 keepalive 连接,减少握手开销:location /ws/ { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; # 启用 upstream keepalive(需在 upstream 块中配置) proxy_set_header X-Real-IP $remote_addr; } -
缓存 WebSocket 初始 HTML/JS 资源
用户访问的网页(含 WebSocket 客户端代码)本身是普通 HTTP 资源,可被proxy_cache正常缓存:location ~ \.(html|js|css|png|jpg|woff2)$ { proxy_cache my_cache; proxy_cache_valid 200 302 1h; proxy_pass http://static_backend; } -
会话粘滞(Sticky Sessions)
若后端是多实例且 WebSocket 状态不共享,用ip_hash或hash $cookie_jsessionid确保同一客户端始终连同一台后端,避免状态丢失——这不是缓存,但提升可靠性:upstream backend { ip_hash; server 192.168.1.10:8080; server 192.168.1.11:8080; }
替代方案:需要缓存实时消息?考虑其他架构
若业务本质是“缓存 WebSocket 下发的消息”(例如行情推送、聊天历史),应将逻辑上移:
- 后端将消息写入 Redis/PubSub,Nginx 不参与;
- 新建一个轻量 HTTP 接口(如
/api/messages?last_id=123),用proxy_cache缓存该接口的 JSON 响应; - 前端通过轮询或 Server-Sent Events(SSE)拉取“可缓存”的历史/快照数据,WebSocket 仅负责低延迟实时更新。
这样既利用了 Nginx 缓存能力,又保留了 WebSocket 的实时性。
Nginx 是优秀的反向代理和负载均衡器,但它不是 WebSocket 消息中间件。把缓存职责交给更合适的组件(Redis、CDN、应用层),让 Nginx 专注连接管理与路由,才是稳健做法。


















