灰度发布思路
灰度发布思路
1. 重写gateway 里面的 负载均衡 filter
2. 拿到对应实例的 列表数据,及元信息
3.获取请求头传过来的版本号,对比实例元信息,找到对应实例(多个可以自定义算法)我这里取第一个
响应式
public class CustomReactiveLoadBalancerClientFilter extends ReactiveLoadBalancerClientFilter
// 核心方法
private Mono<Response<ServiceInstance>> choose(Request<RequestDataContext> lbRequest, String serviceId, Set<LoadBalancerLifecycle> supportedLifecycleProcessors) {
ReactorLoadBalancer<ServiceInstance> loadBalancer = (ReactorLoadBalancer)this.clientFactory.getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
if (loadBalancer == null) {
throw new NotFoundException("No loadbalancer available for " + serviceId);
} else {
supportedLifecycleProcessors.forEach((lifecycle) -> {
lifecycle.onStart(lbRequest);
});
RequestDataContext requestContext = lbRequest.getContext();
HttpHeaders headers = requestContext.getClientRequest().getHeaders();
List<String> versions = headers.get("version");
if(!CollectionUtils.isEmpty(versions)){
log.info("找到 实例 {}",versions.get(0));
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
for (int i = 0; i < instances.size(); i++) {
Map<String, String> metadata = instances.get(i).getMetadata();
String version = metadata.get("version");
if(Objects.equals(versions.get(0),version)){
return Mono.just(new DefaultResponse(instances.get(i)));
}
}
}
return loadBalancer.choose(lbRequest);
}
}
阻塞式
public class CustomLoadBalancerClientFilter extends LoadBalancerClientFilter
// 核心方法
@Override
protected ServiceInstance choose(ServerWebExchange exchange) {
HttpHeaders headers = exchange.getRequest().getHeaders();
List<String> stringList = headers.get("version");
String version = null;
if(!StringUtils.isEmpty(stringList)){
version = stringList.get(0);
}
String host = ((URI) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR)).getHost();
List<ServiceInstance> instances = discoveryClient.getInstances(host);
for (int i = 0; i < instances.size(); i++) {
Map<String, String> metadata = instances.get(i).getMetadata();
String metadataVersion = metadata.get("version");
if(Objects.equals(version,metadataVersion)){
return instances.get(i);
}
}
return super.choose(exchange);
}
元信息
思路就是这样,在重写一个 Feign 调用的 负载算法就ok了,这样就可以实现 多实例 多版本线上 测试,测试新版本没问题 在全面升级。
完善的可以参考 开源 Discovery
elk