灰度发布是利用服务器配置文件的值,在zuul路由时,在choose中利用登陆用户信息进行一些判断,从而影响路由对服务选择的逻辑。
1.配置文件配置:

其中grayVersion的值对应的就是所谓的灰度版本
2.用户信息的配置
可配置在用户表登陆信息中
3.判断逻辑
@Slf4j
public class GrayMetadataRule extends ZoneAvoidanceRule {
public static final String META_DATA_GRAY_VERSION= "grayVersion";
private static final Logger logger = LogManager.getLogger(GrayMetadataRule.class);
private ILoadBalancer iLoadBalancer;
@Override
public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
this.iLoadBalancer = iLoadBalancer;
}
@Override
public ILoadBalancer getLoadBalancer() {
return this.iLoadBalancer;
}
/**
* 1、灰度用户-》 优先选择灰度版本
* 2、非灰度用户-》优先选择正常服务
* @param key
* @return
*/
@Override
public Server choose(Object key) {
//获取所有服务器对象集合
List<Server> serverList = this.getPredicate().getEligibleServers(this.getLoadBalancer().getAllServers(), key);
List<Server> toLBGraySevers = serverList;
try {
if (EmptyUtils.isEmpty(serverList)) {
return null;
}
toLBGraySevers = new ArrayList<>();
List<Server> toLBNormalSevers = new ArrayList<>();
List<Server> otherLBSevers = new ArrayList<>();
String userGrayVersion = "";
String HttpHeadGrayVersion = "";
String gvRuleStr = "";
if (HystrixRequestContext.isCurrentThreadInitialized()) {
//HttpHeader 中的grayVersion 不为空, 优先使用 HttpHeader 中的 grayVersion
HttpHeadGrayVersion = HystrixContext.getGrayVersionInstance().get();
if(EmptyUtils.isNotEmpty(HttpHeadGrayVersion)){
userGrayVersion = HttpHeadGrayVersion;
gvRuleStr = "选取 HttpHeader grayVersion ";
} else {
UserLoginDTO userLoginDTO = HystrixContext.getUserLoginDTOInstance().get();
if (EmptyUtils.isNotEmpty(userLoginDTO)) {
userGrayVersion = userLoginDTO.getGrayVersion();
gvRuleStr = "选取用户 grayVersion ";
}
}
} else{
gvRuleStr = "无HystrixRequestContext, 默认 grayVersion ";
}
logger.info(gvRuleStr + " : " + userGrayVersion);
String lbRuleStr = "灰度匹配";
logger.info("待LB服务数量:" + serverList.size());
for (Server server : serverList) {
DiscoveryEnabledServer discoveryEnabledServer = (DiscoveryEnabledServer) server;
//获取服务器实例,以获取其中启动配置参数
InstanceInfo instanceInfo = discoveryEnabledServer.getInstanceInfo();
Map<String, String> metadata = instanceInfo.getMetadata();
//获取配置灰度值
String metaGrayVersion = metadata.get(META_DATA_GRAY_VERSION);
// 服务grayVersion为空,为普通服务
if (EmptyUtils.isEmpty(metaGrayVersion)) {
toLBNormalSevers.add(server);
// 服务grayVersion与用户一致,为toLB灰度服务
} else if (metaGrayVersion.equals(userGrayVersion)){
toLBGraySevers.add(server);
// 其他未匹配服务
} else {
otherLBSevers.add(server);
}
logger.info("待LB服务:" + server + " grayVersion: " + metaGrayVersion);
}
// 无匹配的灰度服务,选取普通服务
if (EmptyUtils.isEmpty(toLBGraySevers)) {
lbRuleStr = "无匹配的灰度服务,选取普通服务";
toLBGraySevers.addAll(toLBNormalSevers);
}
// 无匹配的灰度服务,无普通服务, 选取其他grayVersion的灰度服务
if (EmptyUtils.isEmpty(toLBGraySevers)) {
lbRuleStr = "无匹配的灰度服务,无普通服务, 选取其他grayVersion的灰度服务";
toLBGraySevers.addAll(otherLBSevers);
}
logger.info("初选LB服务规则: "+ lbRuleStr + " : " + toLBGraySevers);
} catch (Exception e) {
logger.error("gray LB fail:", e.getMessage(), e);
}
return originChoose(toLBGraySevers, key);
}
private Server originChoose(List<Server> noMetaServerList, Object key) {
//路由规则后最终选取路由服务
Optional<Server> server = getPredicate().chooseRoundRobinAfterFiltering(noMetaServerList, key);
logger.info("终选LB服务:" + server);
if (server.isPresent()) {
return server.get();
} else {
return null;
}
}
}