程序地带

SpringCloud LoadBalancer灰度策略实现


如何使用 Spring Cloud 2020 中重磅推荐的负载均衡器 Spring Cloud LoadBalancer (下文简称 SCL),如何扩展负载均衡策略? 你将从本文中获取到答案


快速上手 SCL 如果项目中想使用 SCL,则仅需要添加如下 maven 依赖即可


<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

SCL 是构建服务发现的基础上,由java基础于目前 Spring Cloud Alibaba 并未兼容 SCL (具体兼容方案可以参考 pig),当然你可以选择使用Eureka 测试。


若将 RestTemplate 和 客户端负载均衡结合使用,在 bean 定义上增加 @LoadBalanced 注解即可.


@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

个性化负载均衡策略 SCL 内置的负载均衡策略


目前版本 (spring cloud 2020) 内置轮询、随机的负载均衡策略,默认轮询策略。


当然可以通过 LoadBalancerClient 注解,指定服务级别的负载均衡策略


@LoadBalancerClient(value = "demo-provider", configuration = RandomLoadbalancerConfig.class)
public class RandomLoadbalancerConfig {
@Bean
public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}

自定义负载均衡策略 通过上文可知,目前 SCL 支持的负载均衡策略相较于 Ribbon 还是较少,需要开发者自行实现,好在 SCL 提供了便捷的 API 方便扩展使用。 这里演示自定义一个基于注册中心元数据的灰度负载均衡策略。


定义灰度负载均衡策略


@Slf4j
public class GrayRoundRobinLoadBalancer extends RoundRobinLoadBalancer {
private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
private String serviceId;
@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
.getIfAvailable(NoopServiceInstanceListSupplier::new);
return supplier.get(request).next().map(serviceInstances -> getInstanceResponse(serviceInstances, request));
}
Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, Request request) {
// 注册中心无可用实例 抛出异常
if (CollUtil.isEmpty(instances)) {
log.warn("No instance available {}", serviceId);
return new EmptyResponse();
}
DefaultRequestContext requestContext = (DefaultRequestContext) request.getContext();
RequestData clientRequest = (RequestData) requestContext.getClientRequest();
HttpHeaders headers = clientRequest.getHeaders();
String reqVersion = headers.getFirst(CommonConstants.VERSION);
if (StrUtil.isBlank(reqVersion)) {
return super.choose(request).block();
}
// 遍历可以实例元数据,若匹配则返回此实例
for (ServiceInstance instance : instances) {
NacosServiceInstance nacosInstance = (NacosServiceInstance) instance;
Map<String, String> metadata = nacosInstance.getMetadata();
String targetVersion = MapUtil.getStr(metadata, CommonConstants.VERSION);
if (reqVersion.equalsIgnoreCase(targetVersion)) {
log.debug("gray requst match success :{} {}", reqVersion, nacosInstance);
return new DefaultResponse(nacosInstance);
}
}
// 降级策略,使用轮询策略
return super.choose(request).block();
}
}

针对客户端注入灰度负载均衡策略 @LoadBalancerClient(value = “demo-provider”, configuration = GrayRoundLoadbalancerConfig.class) 服务实例定义版本号


请求携带版本号,测试使用 curl --location --request GET ‘http://localhost:6060/req?key=b’ –header ‘VERSION: b’ 优化负载均衡策略注入 如上文所述,所有的个性化负载策略都需要手动通过 LoadBalancerClient 注入非常的不方便。 我们可以参考 LoadBalancerClients 的批量注入逻辑构造自己的 BeanRegistrar


public class GrayLoadBalancerClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
Field[] fields = ReflectUtil.getFields(ServiceNameConstants.class);
// 遍历服务名称,注入支持灰度策略的负载均衡器
for (Field field : fields) {
Object fieldValue = ReflectUtil.getFieldValue(ServiceNameConstants.class, field);
registerClientConfiguration(registry, fieldValue, GrayLoadBalancerClientConfiguration.class);
}
}
}

源码 https://gitee.com/log4j/pig,欢迎署名转载 <<<


好文要顶 关注我 收藏该文


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chinaherolts2008/article/details/112689488

随机推荐

can硬件滤波 stm32cubemx_CAN总线面向航天卫星的应用分析

can硬件滤波 stm32cubemx_CAN总线面向航天卫星的应用分析

1、引言can总线是由德国bosch公司为现实汽车测量和执行部件之间的数据通讯而设计的、支持分布式控制及实时控制的串行通讯网络。can总线通讯的波特率可高达1mbps,最远距离可达10k...

溯水襄陵 阅读(932)

深度好文:Linux文件系统剖析

深度好文:Linux文件系统剖析

Linux文件系统体系结构是一个对复杂系统进行抽象化的有趣例子。通过使用一组通用的API函数,Linux可以在许多种存储设备上支持许多种文件系统。例如,read函数调用可以...

linux大本营 阅读(345)

curve函数 roc_零数学理解ROC-AUC指标

curve函数 roc_零数学理解ROC-AUC指标

没有数学或公式,只有图像和动画。>PhotobyKalenEmsleyonUnsplash了解轴这是典型的ROC图:在进行任何其他操作之前,我们需要了解轴的含义。在不...

weixin_39859715 阅读(1000)