灰度方案
目前现状分析
- zuul做网关,统一所有内部服务的入口
- 目前没有用 eureka 注册中心 【目前公司架构dubbo,注册中心zookeeper】
- 采用类似nginx的反向代理,ribbon路由
- 服务一般部署多台,比如A,B,C三台,每次只拿一台做灰度机器
- 只支持zuul网关下http协议的灰度
灰度方式
- zuul本地缓存是否开启全局灰度【提高性能不灰度的时候不用调用redis】
- 每个服务的灰度控制在redis中, 配置格式如下
- 根据简单用户id去找到toServerId灰度机器
[
{
"toServerId": "localhost:8585",
"userList": null,
"app": "tsms",
"serverIdList": [
"localhost:8080",
"localhost:8585"
],
"graying": true
}
]
灰度结合发布的流程
- 发布之前,将severId A为localhost:8080 执行接口标记灰度
- 流量在A 全部切换完 等一分钟差不多
- 运维发布平台选择 发布到A机器
- 用设置的灰度userid,访问就会访问到A机器 刚发布的新版本
- 等半个小时 没有问题,将 B 切换为灰度机器
- 发布b机器 ,然后将graying标记为false
- 上线完成【简单的几台集群可以完全可以满足】
实现
- 全局灰度开启,redis订阅,修改gateway集群中所有的本地缓存
- 自定义ribbon复杂均衡
tsms:
ribbon:
listOfServers: localhost:8080, localhost:8585
tsms:
ribbon:
NFLoadBalancerRuleClassName: com.xxx.xxx.gateway.ribbon.GrayLoadBalancerRule
GrayLoadBalancerRule 我们自定义的ribbon复杂均衡
@Override
public Server choose(Object key) {
RequestContext requestContext = RequestContext.getCurrentContext();
权限控制filter解码后 得到用户id
String userId = (String) requestContext.get(Constants.ACCESS_USER_ID);
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
if (loadBalancer == null) {
log.warn("no load balancer");
return null;
}
List<Server> serverList = loadBalancer.getReachableServers();
String client = loadBalancer.getClientConfig().getClientName();
GrayHolderInfo grayHolderInfo = grayService.grayByUserId(client, serverList, userId);
if (grayHolderInfo.getGrayServer().isPresent()) {
return grayHolderInfo.getGrayServer().get();
}
轮询
return roundRuleChoose(client, loadBalancer, grayHolderInfo);
}
需要做的
网友评论