SpringCloudLoadbalancer

Spring Cloud 2020版本以后,默认移除了对Netflix的依赖,其中就包括Ribbon,官方默认推荐使用Spring Cloud Loadbalancer正式替换Ribbon,并成为了Spring Cloud负载均衡器的唯一实现。

简单使用

导入依赖:

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

添加配置类:

@Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
java

基本原理

其基本原理如下:

1. RestTemplate

RestTemplate提供了一个setInterceptors方法,用于设置拦截器。

/** * Set the request interceptors that this accessor should use. * <p>The interceptors will get immediately sorted according to their * {@linkplain AnnotationAwareOrderComparator#sort(List) order}. * @see #getRequestFactory() * @see AnnotationAwareOrderComparator */ public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) { Assert.noNullElements(interceptors, "'interceptors' must not contain null elements"); // Take getInterceptors() List as-is when passed in here if (this.interceptors != interceptors) { this.interceptors.clear(); this.interceptors.addAll(interceptors); AnnotationAwareOrderComparator.sort(this.interceptors); } }
JAVA

2. LoadBalancerAutoConfiguration

在这里进行拦截器的注入:

@Configuration(proxyBeanMethods = false) @Conditional(RetryMissingOrDisabledCondition.class) static class LoadBalancerInterceptorConfig { @Bean // LoadBalancerInterceptor是实现了ClientHttpRequestInterceptor接口的实现类 public LoadBalancerInterceptor loadBalancerInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) { return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); } @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) { return restTemplate -> { List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } }
java

其中LoadBalancerInterceptor是实现了ClientHttpRequestInterceptor接口的实现类,主要由该类进行请求的负载均衡

其中这个类在实例化时需要提供一个LoadBalancerClient,表示负载均衡客户端,用于处理负载均衡的具体逻辑,Spring只提供了一个BlockingLoadBalancerClient类。

3. LoadBalancerClient

这是BlockingLoadBalancerClient实现的接口,它还继承了ServiceInstanceChooser

public interface LoadBalancerClient extends ServiceInstanceChooser { // 执行请求 <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException; // 执行请求 <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException; // 这里方法主要是将我们的服务名替换为域名 URI reconstructURI(ServiceInstance instance, URI original); } public interface ServiceInstanceChooser { // 从服务中选择一个服务实例 ServiceInstance choose(String serviceId); // 从服务中为指定的request选择一个服务实例 <T> ServiceInstance choose(String serviceId, Request<T> request); }
java

BlockingLoadBalancerClientexecute方法进来,一路追到choose方法发现它最终是调用ReactiveLoadBalancer的实现类来实现复杂均衡算法的。

@Override public <T> ServiceInstance choose(String serviceId, Request<T> request) { // 获取负载均衡算法 ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId); if (loadBalancer == null) { return null; } // 调用choose方法进行负载均衡 Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose(request)).block(); if (loadBalancerResponse == null) { return null; } return loadBalancerResponse.getServer(); }
java

实现类

可以发现有两个实现类

  • RandomLoadBalancer:随机访问
  • RoundRobinLoadBalancer:轮询

来看一下getInstance的具体实现:

// LoadBalancerClientFactory @Override public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) { return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class); } // NamendContextFactory // getInstance:根据名称和类型获取bean public <T> T getInstance(String name, Class<T> type) { AnnotationConfigApplicationContext context = this.getContext(name); try { return context.getBean(type); } catch (NoSuchBeanDefinitionException var5) { return null; } }
java

如果要了解更多,请先查阅:NamendContextFactory的使用与源码

自定义负载均衡配置

只需要通过注解@LoadBalancerClient@LoadBalancerClients就可以轻松实现配置不同的负载均衡策略。

Spring Cloud Loadbalancer源码解析和自定义负载均衡策略实现 - 知乎 (zhihu.com)

LoadBalancer集成Nacos实现负载均衡_Pymj的博客-CSDN博客