首頁>技術>

如何使用 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[1]),當然你可以選擇使用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);  } }}
參考資料

[1]

相容Spring Cloud 2020 方案: https://gitee.com/log4j/pig

12
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Java本地快取神器——Caffeine(一)