split_clients指令可基于客户端标识对WebSocket请求做确定性分流以实现灰度发布;需配合proxy_http_version 1.1、Upgrade/Connection头透传、禁用缓冲与缓存等配置保障WebSocket长连接稳定;通过哈希一致性绑定用户至固定后端,结合upstream和proxy_pass动态路由,并通过响应头与日志记录验证分组。

使用 split_clients 指令可以基于客户端标识(如 IP、Cookie 或请求头)对 WebSocket 连接请求做确定性分流,从而实现灰度发布与流量切分。它本身不感知协议类型,但配合 Nginx 的 upgrade 和 connection 头处理逻辑,能稳定支撑 WebSocket 的灰度路由。
确保 Nginx 支持 WebSocket 升级
WebSocket 依赖 HTTP/1.1 的 Upgrade: websocket 协议升级机制,Nginx 必须透传关键头部并维持长连接:
- 在
location块中显式设置:proxy_http_version 1.1;、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection "upgrade"; - 禁用缓冲和超时干扰:
proxy_buffering off;、proxy_read_timeout 86400;(或按业务设定合理值) - 避免使用
proxy_cache或gzip等可能中断流式传输的模块
用 split\_clients 定义灰度分组
split_clients 基于哈希值做一致性分流,适合长期绑定用户到固定后端(如灰度环境),避免连接反复跳转导致状态丢失:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 以用户 IP 为例(推荐用于内部灰度):
split_clients $remote_addr $backend_group {<br> 5% ".gray";<br> * ""; <br>}
表示 5% 的 IP 地址哈希落入.gray组,其余走默认后端 - 若需更精细控制(如按 Cookie 中的灰度 ID):
set $gray_id $cookie_gray_id;<br>split_clients $gray_id $backend_group {<br> 10% ".gray";<br> * ""; <br>}
注意:空$gray_id会归入*分支,建议前端统一注入或 fallback 到 IP
结合 upstream 实现动态后端路由
将 split_clients 输出的变量用于 proxy_pass,指向不同 upstream 块:
- 定义两个 upstream:
upstream backend_prod { server 10.0.1.10:8080; }<br>upstream backend_gray { server 10.0.1.20:8080; } - 在 location 中路由:
location /ws/ {<br> proxy_pass http://backend$backend_group;<br> # 其他 WebSocket 必需配置...<br>}
当$backend_group为.gray时,实际转发到backend_gray;为空时等价于backend(即backend_prod) - 注意:
proxy_pass后不能带 URI 路径(如/ws/),否则变量拼接会出错;路径透传由 location 匹配保证
验证与可观测性要点
灰度发布成败取决于能否准确识别和追踪连接归属:
- 在响应头中注入分组标识便于前端或日志排查:
add_header X-Backend-Group $backend_group; - 记录连接来源信息到 access log:
log_format ws_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$backend_group"';<br>access_log /var/log/nginx/ws-access.log ws_log;
- WebSocket 连接建立是一次性 HTTP 请求,分流只发生在握手阶段;后续帧通信复用该 TCP 连接,无需重复判断

















