spring cloud gateway + nacos 灰度发布
原理
在客户端请求时的 header 带入 一个标签,如: svc_version服务器应用 启动的时候 打上标签,可以和客户端的属性一致,如 svc_version请求到网关的时候,网关负载过滤带 svc_version 属性的服务器应用列表返回已经匹配客户端 svc_version 的服务器应用 列表在这些列表中请求转发客户端请求
应用列表
nacos-user : 普通应用nacos-gateway
nacos-gateway
引入依赖
注意一定要引入 spring-cloud-loadbalancer!!
实现 灰度负载LoadBalancer
public class GreyRoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final String GREP_HEADER = "svc_version";
private static final Log log = LogFactory.getLog(GreyRoundRobinLoadBalancer.class);
final AtomicInteger position;
final String serviceId;
ObjectProvider
/**
* @param serviceInstanceListSupplierProvider a provider of
* {@link ServiceInstanceListSupplier} that will be used to get available instances
* @param serviceId id of the service for which to choose an instance
*/
public GreyRoundRobinLoadBalancer(ObjectProvider
String serviceId) {
this(serviceInstanceListSupplierProvider, serviceId, new Random().nextInt(1000));
}
/**
* @param serviceInstanceListSupplierProvider a provider of
* {@link ServiceInstanceListSupplier} that will be used to get available instances
* @param serviceId id of the service for which to choose an instance
* @param seedPosition Round Robin element position marker
*/
public GreyRoundRobinLoadBalancer(ObjectProvider
String serviceId, int seedPosition) {
this.serviceId = serviceId;
this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
this.position = new AtomicInteger(seedPosition);
}
@SuppressWarnings("rawtypes")
@Override
public Mono
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get(request)
.flatMap(list -> {
RequestDataContext context = (RequestDataContext) request.getContext();
String version = context.getClientRequest().getHeaders().getFirst(GREP_HEADER);
boolean b = StringUtils.hasText(version) ? true : false;
List
if (b) {
return instance.getMetadata().containsKey(GREP_HEADER) && instance.getMetadata().get(GREP_HEADER).equals(version);
}
return !instance.getMetadata().containsKey(GREP_HEADER);
}).collect(Collectors.toList());
return Mono.justOrEmpty(collect);
})
.next()
.map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));
}
private Response
List
Response
if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
}
return serviceInstanceResponse;
}
private Response
if (instances.isEmpty()) {
if (log.isWarnEnabled()) {
log.warn("No servers available for service: " + serviceId);
}
return new EmptyResponse();
}
// Ignore the sign bit, this allows pos to loop sequentially from 0 to
// Integer.MAX_VALUE
int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
ServiceInstance instance = instances.get(pos % instances.size());
return new DefaultResponse(instance);
}
}
配置
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
public class GreyLoadBalancerClientConfiguration {
private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 173827465;
@Bean
// @Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)
public ReactorLoadBalancer
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new GreyRoundRobinLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}
向容器注入自定义 LoadBalancer:
@Configuration
@LoadBalancerClients(defaultConfiguration = GreyLoadBalancerClientConfiguration.class)
public class CusLoadBalancerClientConfiguration {
}
@LoadBalancerClients, 重要!!,给所有的负载都加上自定义的灰度负载器
使用
启用应用nacos-user, 一个打了标签,一个没有打标签:
在客户端请求网关时,headers带上 svc_version=1.0, 那么请求就会打到 5558这个应用
参考 nacos loadbalancer:
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnLoadBalancerNacos
@ConditionalOnNacosDiscoveryEnabled
@LoadBalancerClients(defaultConfiguration = NacosLoadBalancerClientConfiguration.class)
public class LoadBalancerNacosAutoConfiguration {
}
good luck!
好文链接
发表评论