一、灰度发布概述
灰度发布(金丝雀发布)是一种渐进式发布策略:
- 先让小部分用户使用新版本
- 观察指标,逐步扩大范围
- 发现问题快速回滚
二、灰度策略
1. 按比例灰度
新版本: 10% → 30% → 50% → 100%
旧版本: 90% → 70% → 50% → 0%
2. 按用户特征灰度
- 用户ID取模
- 用户标签(VIP、新用户等)
- 地域、设备类型
3. 按流量特征灰度
- 请求Header
- Cookie
- URL参数
三、实现方案
Nginx实现
nginx
upstream backend_v1 {
server 192.168.1.10:8080;
}
upstream backend_v2 {
server 192.168.1.11:8080;
}
split_clients "${remote_addr}" $backend {
10% backend_v2;
* backend_v1;
}
server {
location / {
proxy_pass http://$backend;
}
}
网关层实现(Spring Cloud Gateway)
yaml
spring:
cloud:
gateway:
routes:
- id: service-v1
uri: lb://service-v1
predicates:
- Path=/api/**
- Weight=group1, 90
- id: service-v2
uri: lb://service-v2
predicates:
- Path=/api/**
- Weight=group1, 10
服务框架实现(Dubbo)
yaml
dubbo:
consumer:
loadbalance: grayLoadBalance
java
public class GrayLoadBalance implements LoadBalance {
@Override
public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
String version = invocation.getAttachment("gray-version");
if ("v2".equals(version)) {
// 返回新版本Invoker
return findInvoker(invokers, "v2");
}
// 按比例分配
if (Math.random() < 0.1) {
return findInvoker(invokers, "v2");
}
return findInvoker(invokers, "v1");
}
}
四、全链路灰度
核心思路
请求链路上传递灰度标记,各服务根据标记路由。
Gateway → ServiceA → ServiceB → ServiceC
↓ ↓ ↓ ↓
灰度标记 → 透传标记 → 透传标记 → 透传标记
实现代码
java
// 网关设置灰度标记
@Component
public class GrayFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
if (isGrayUser(userId)) {
exchange.getRequest().mutate()
.header("X-Gray-Version", "v2")
.build();
}
return chain.filter(exchange);
}
}
// 服务透传标记
public class GrayContextHolder {
private static final ThreadLocal<String> VERSION = new ThreadLocal<>();
public static void setVersion(String version) {
VERSION.set(version);
}
public static String getVersion() {
return VERSION.get();
}
}
// Feign拦截器透传
public class GrayFeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
String version = GrayContextHolder.getVersion();
if (version != null) {
template.header("X-Gray-Version", version);
}
}
}
五、灰度监控
关键指标
| 指标 | 说明 |
|---|---|
| QPS | 新旧版本对比 |
| 响应时间 | P99延迟对比 |
| 错误率 | 异常比例对比 |
| 业务指标 | 转化率、成功率 |
自动化决策
java
public class GrayDecisionService {
public boolean shouldExpandGray() {
// 对比新旧版本指标
double v1ErrorRate = getErrorRate("v1");
double v2ErrorRate = getErrorRate("v2");
// 新版本错误率更低,扩大灰度
if (v2ErrorRate < v1ErrorRate * 0.8) {
return true;
}
// 新版本错误率更高,回滚
if (v2ErrorRate > v1ErrorRate * 1.5) {
rollback();
return false;
}
return false;
}
}
六、总结
灰度发布是保障发布安全的重要手段:
- 策略选择:按比例、按用户、按特征
- 实现层次:网关层、服务层、全链路
- 监控决策:自动化灰度推进
思考题:你们的灰度发布流程是怎样的?
个人观点,仅供参考