2021-01-15

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

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

@Bean@LoadBalancedpublic 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 方便扩展使用。 这里演示自定义一个基于注册中心元数据的灰度负载均衡策略。

  • 定义灰度负载均衡策略

@Slf4jpublic 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,欢迎署名转载 <<<









原文转载:http://www.shaoqun.com/a/508904.html

跨境电商:https://www.ikjzd.com/

杨颜:https://www.ikjzd.com/w/1820

刘小东:https://www.ikjzd.com/w/1853


如何使用SpringCloud2020中重磅推荐的负载均衡器SpringCloudLoadBalancer(下文简称SCL),如何扩展负载均衡策略?你将从本文中获取到答案快速上手SCL如果项目中想使用SCL,则仅需要添加如下maven依赖即可<dependency> <groupId>org.springframework.cloud</groupId> <
bestbuy:bestbuy
anker:anker
深圳2020去哪看花灯?深圳世界之窗夜场有表演吗?:深圳2020去哪看花灯?深圳世界之窗夜场有表演吗?
速卖通引流小技巧教你如何引流打造爆款:速卖通引流小技巧教你如何引流打造爆款
深圳翠竹地铁站附近有什么好玩好吃的地方吗?:深圳翠竹地铁站附近有什么好玩好吃的地方吗?

No comments:

Post a Comment