bigywater.tech
Spring · 132

灰度发布:基于请求头的路由

灰度发布在网关层怎么做?Header、Weight 哪个更合适?同一个用户会不会一会儿新版一会儿旧版?lb:// 路由为什么返回 503?LoadBalancer 的权重是精确的吗?这篇在 Spring Cloud Gateway 5.0.3 与 LoadBalancer 上用两个版本的真实后端逐项统计。

794 / 206
一千次请求在 Weight 80/20 下落到 v1、v2 的次数,是随机的
800 / 200
LoadBalancer 的 weighted 配置在 80/20 权重下 1000 次请求的分布,是精确的
2 / 18
同一个用户在 Weight 路由下连续 20 次请求里 v2 与 v1 的次数,会来回跳

按头路由

实测 · 本机执行输出
  canary 路由写在前面:不带头 → v1;X-Canary: true → v2;X-Canary: false → v1
  default 路由写在前面:X-Canary: true → v1(canary 路由永远不会命中)

canary 路由要写在前面。

按权重

实测 · 本机执行输出
  1000 次请求落到各版本的次数:{'v1': 794, 'v2': 206}
  同一个用户(X-User: 1001)连续 20 次请求:11111221111111111111(v1 共 18 次、v2 共 2 次)

接近比例但随机,同一用户会来回跳。

按用户分桶

实测 · 本机执行输出
  200 个用户里:每个用户 3 次请求结果都一致的 200 个;去 v2 的用户 40 个、去 v1 的 160 个

同一用户始终同版本。

LoadBalancer 权重

实测 · 本机执行输出
  只引入 gateway starter(没有 spring-cloud-starter-loadbalancer):GET /api/x → HTTP 503,响应体 {"path":"/api/x","status":503,"error":"Service Unavailable",}
  加上 spring-cloud-starter-loadbalancer,不配权重(默认轮询)200 次:{'v1': 100, 'v2': 100}
  weighted + weight 80/20,1000 次:{'v1': 800, 'v2': 200}

lb:// 需要 loadbalancer starter;weighted 按 metadata.weight 精确分配。

会话保持

实测 · 本机执行输出
  只开 request-based-sticky-session:第一次请求的响应头里 Set-Cookie = 没有;不带 cookie 连续 20 次请求 {'v1': 10, 'v2': 10}
  再加 sticky-session.add-service-instance-cookie=true:第一次请求的响应头里 Set-Cookie = 没有;不带 cookie 连续 20 次请求 {'v1': 10, 'v2': 10}

sticky-session 配置在网关里没有看到 Set-Cookie。

分步演示

灰度发布
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。两个后端是 Python 线程里的 HTTP 服务,返回 v1 / v2;网关路由用 -D 属性配置;lb:// 的实例来自 SimpleDiscoveryClient 的配置;Weight 的数字是随机的,每次运行会不同
    • 没有验证:真实注册中心(Nacos / Eureka)的 metadata 版本号配合自定义 ServiceInstanceListSupplier 做灰度;请求头透传到下游服务的链路灰度(整条调用链都走 v2);Weight 路由权重动态调整;按 Cookie / Query / 地域做灰度的 Predicate;灰度与熔断、限流的配合;request-based-sticky-session 在网关里为什么没有 Set-Cookie;本站微服务系列里的流量切分一篇(microservice-traffic-splitting)
    京ICP备2026067502号-1京公网安备11010502063487号