微服务LoadBalancer源码分析

180 阅读7分钟

Spring Cloud LoadBalancer属于官方开源客户端负载均衡器,底层也是基于RestTemplate拦截器(ClientHttpRequestInterceptor)扩展实现,实现原理与Ribbon相似,区别在于LoadBalancerClient和上下文构建实现有所区别。

01 自动装配

1.1 客户端配置

LoadBalancer依赖spring-cloud-loadbalancer.jar配置自动装配类LoadBalancerAutoConfiguration与BlockingLoadBalancerClientAutoConfiguration,借助spring.factories文件实现配置发现和解析。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration
@AutoConfigureBefore({ReactorLoadBalancerClientAutoConfiguration.class, LoadBalancerBeanPostProcessorAutoConfiguration.class, ReactiveLoadBalancerAutoConfiguration.class})
public class LoadBalancerAutoConfiguration {
    // 客户端配置, 主要通过@LoadBalancerClients注解配置注入
    private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;

    public LoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
        this.configurations = configurations;
    }
    
    @Bean
    @ConditionalOnMissingBean
    public LoadBalancerZoneConfig zoneConfig(Environment environment) {
        return new LoadBalancerZoneConfig(environment.getProperty("spring.cloud.loadbalancer.zone"));
    }

    // 目的是构建LoadBalancer上下文
    @Bean
    @ConditionalOnMissingBean
    public LoadBalancerClientFactory loadBalancerClientFactory() {
        LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory();
        clientFactory.setConfigurations((List)this.configurations.getIfAvailable(Collections::emptyList));
        return clientFactory;
    }
}

LoadBalancer通过LoadBalancerClientFactory#getContext方法创建客户端配置IOC容器,全局默认客户端配置实现就是LoadBalancerClientConfiguration

public class LoadBalancerClientFactory extends NamedContextFactory<LoadBalancerClientSpecification> implements ReactiveLoadBalancer.Factory<ServiceInstance> {
    public static final String NAMESPACE = "loadbalancer";
    public static final String PROPERTY_NAME = NAMESPACE + ".client.name";
    public LoadBalancerClientFactory() {
        super(LoadBalancerClientConfiguration.class, NAMESPACE, PROPERTY_NAME);
    }
}

LoadBalancer客户端配置是通过@LoadBalancerClients@LoadBalancerClient注解提供开发人员配置,具体解析过程详见([1.1.3 客户端配置]),创建LoadBalancerClientFactory使用setConfigurations方法设置客户端配置。

public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
    implements DisposableBean, ApplicationContextAware {
    private final String propertySourceName;
    private final String propertyName;
    // 客户端容器缓存
    private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
    // 配置类
    private Map<String, C> configurations = new ConcurrentHashMap<>();
    // 父容器
    private ApplicationContext parent;
    // 默认全局配置
    private Class<?> defaultConfigType;

    public NamedContextFactory(Class<?> defaultConfigType, String propertySourceName, String propertyName) {
        this.defaultConfigType = defaultConfigType;
        this.propertySourceName = propertySourceName;
        this.propertyName = propertyName;
    }
    
    protected AnnotationConfigApplicationContext getContext(String name) {
        if (!this.contexts.containsKey(name)) {
            synchronized (this.contexts) {
                if (!this.contexts.containsKey(name)) {
                    this.contexts.put(name, createContext(name));
                }
            }
        }
        return this.contexts.get(name);
    }
    
    // 创建上下文: 每个客户端使用一个IOC容器管理
    protected AnnotationConfigApplicationContext createContext(String name) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 指定客户端配置
        if (this.configurations.containsKey(name)) {
            for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
                // 注册配置实例
                context.register(configuration);
            }
        }
        // 全局默认配置
        for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
            if (entry.getKey().startsWith("default.")) {
                for (Class<?> configuration: entry.getValue().getConfiguration()) {
                    context.register(configuration);
                }
            }
        }
        // 全局配置类
        context.register(PropertyPlaceholderAutoConfiguration.class, defaultConfigType);
        context.getEnvironment().getPropertySources().addFirst(new MapPropertySource (
                this.propertySourceName,
                Collections.<String, Object>singletonMap(this.propertyName, name))
        );
        // 设置IOC父容器
        if (this.parent != null) {
            context.setParent(this.parent);
            context.setClassLoader(this.parent.getClassLoader());
        }
        context.setDisplayName(generateDisplayName(name));
        // 刷新IOC容器
        context.refresh();
        return context;
    }
    protected String generateDisplayName(String name) {
        return this.getClass().getSimpleName() + "-" + name;
    }
}

1.1.1 默认全局配置类

LoadBalancer全局默认配置类为LoadBalancerClientConfiguration,提供Reactor获取服务实例,以及服务实例负载选择。

LoadBalancer使用开关配置开通不同服务实例提供者,如果ReactiveDiscoveryClient实例存在,默认情况通过ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().build(context)创建ServiceInstanceListSupplier。如果DiscoveryClient实例存在,那么默认情况通过ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().build(context)创建ServiceInstanceListSupplier。

@ConditionalOnDiscoveryEnabled
public class LoadBalancerClientConfiguration {
    private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 193827465;
    
    @Bean
    @ConditionalOnMissingBean
    public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(
        Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnReactiveDiscoveryEnabled
    @Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)
    public static class ReactiveSupportConfiguration {
        // 默认配置
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(ReactiveDiscoveryClient.class)
        @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", 
                               havingValue = "default", 
                               matchIfMissing = true)
        public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
            return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient().withCaching().build(context);
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(ReactiveDiscoveryClient.class)
        @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", 
                               havingValue = "zone-preference")
        public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
            return ServiceInstanceListSupplier.builder()
                   .withDiscoveryClient().withZonePreference().withCaching().build(context);
        }
        
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(ReactiveDiscoveryClient.class)
        @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", 
                               havingValue = "health-check")
        public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
            return ServiceInstanceListSupplier.builder().withDiscoveryClient()
                   .withHealthChecks().withCaching().build(context);
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(ReactiveDiscoveryClient.class)
        public ServiceInstanceSupplier discoveryClientServiceInstanceSupplier(
            ReactiveDiscoveryClient discoveryClient, Environment env, 
            ApplicationContext context) {
            DiscoveryClientServiceInstanceSupplier delegate = new DiscoveryClientServiceInstanceSupplier(discoveryClient, env);
            ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context.getBeanProvider(LoadBalancerCacheManager.class);
            if (cacheManagerProvider.getIfAvailable() != null) {
                return new CachingServiceInstanceSupplier(delegate, cacheManagerProvider.getIfAvailable());
            }
            return delegate;
        }
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnBlockingDiscoveryEnabled
    @Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)
    public static class BlockingSupportConfiguration {
        // 默认配置
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(DiscoveryClient.class)
        @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", 
                               havingValue = "default", 
                               matchIfMissing = true)
        public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {
            return ServiceInstanceListSupplier.builder()
                   .withBlockingDiscoveryClient().withCaching().build(context);
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(DiscoveryClient.class)
        @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", 
                               havingValue = "zone-preference")
        public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier(
                ConfigurableApplicationContext context) {
            return ServiceInstanceListSupplier.builder()
                    .withBlockingDiscoveryClient().withZonePreference()
                    .withCaching().build(context);
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(DiscoveryClient.class)
        @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", 
                               havingValue = "health-check")
        public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
            return ServiceInstanceListSupplier.builder()
                    .withBlockingDiscoveryClient().withHealthChecks()
                    .withCaching().build(context);
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(DiscoveryClient.class)
        public ServiceInstanceSupplier discoveryClientServiceInstanceSupplier(
            DiscoveryClient discoveryClient, Environment env, ApplicationContext context) {
            DiscoveryClientServiceInstanceSupplier delegate = new DiscoveryClientServiceInstanceSupplier(discoveryClient, env);
            ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context.getBeanProvider(LoadBalancerCacheManager.class);
            if (cacheManagerProvider.getIfAvailable() != null) {
                return new CachingServiceInstanceSupplier(delegate, cacheManagerProvider.getIfAvailable());
            }
            return delegate;
        }
    }
}
public final class ServiceInstanceListSupplierBuilder {
    private Creator baseCreator;
    private DelegateCreator cachingCreator;
    private final List<DelegateCreator> creators = new ArrayList<>();

    public ServiceInstanceListSupplierBuilder withBlockingDiscoveryClient() {
        this.baseCreator = context -> {
            // 获取DiscoveryClient客户端
            DiscoveryClient discoveryClient = context.getBean(DiscoveryClient.class);
            return new DiscoveryClientServiceInstanceListSupplier(discoveryClient, context.getEnvironment());
        };
        return this;
    }
    public ServiceInstanceListSupplierBuilder withDiscoveryClient() {
        this.baseCreator = context -> {
            // 全局默认配置获取服务发现客户端
            ReactiveDiscoveryClient discoveryClient = context.getBean(ReactiveDiscoveryClient.class);
            return new DiscoveryClientServiceInstanceListSupplier(discoveryClient, context.getEnvironment());
        };
        return this;
    }
    public ServiceInstanceListSupplierBuilder withCaching() {
        this.cachingCreator = (context, delegate) -> {
            ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context.getBeanProvider(LoadBalancerCacheManager.class);
            if (cacheManagerProvider.getIfAvailable() != null) {
                return new CachingServiceInstanceListSupplier(delegate, cacheManagerProvider.getIfAvailable());
            }
            return delegate;
        };
        return this;
    }
    public ServiceInstanceListSupplier build(ConfigurableApplicationContext context) {
        ServiceInstanceListSupplier supplier = baseCreator.apply(context);
        for (DelegateCreator creator : creators) {
            supplier = creator.apply(context, supplier);
        }
        if (this.cachingCreator != null) {
            supplier = this.cachingCreator.apply(context, supplier);
        }
        return supplier;
    }
}

1.1.2 服务发现客户端

创建ServiceInstanceListSupplier需要依赖ReactiveDiscoveryClient或者DiscoveryClient实例,其中Nacos提供依赖spring-cloud-starter-alibaba-nacos-discovery配置自动装配。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
  com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration
public class NacosReactiveDiscoveryClient implements ReactiveDiscoveryClient {
    private NacosServiceDiscovery serviceDiscovery;

    public NacosReactiveDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
        this.serviceDiscovery = nacosServiceDiscovery;
    }
    @Override
    public Flux<ServiceInstance> getInstances(String serviceId) {
        return Mono.justOrEmpty(serviceId).flatMapMany(loadInstancesFromNacos())
              .subscribeOn(Schedulers.boundedElastic());
    }
}

1.1.3 客户端配置

LoadBalancer申明@LoadBalancerClients@LoadBalancerClient提供开发人员配置客户端,使用客户端注册者(LoadBalancerClientConfigurationRegistrar)解析为LoadBalancerClientSpecification,接着直接注入IOC容器。所以,LoadBalancerClientFactory实例就能够找到这些客户端配置。

@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClients {
	LoadBalancerClient[] value() default {};
	Class<?>[] defaultConfiguration() default {};
}

@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClient {
	@AliasFor("name")
	String value() default "";
	@AliasFor("value")
	String name() default "";
	Class<?>[] configuration() default {};
}
public class LoadBalancerClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
    private static String getClientName(Map<String, Object> client) {
        if (client == null) {
                return null;
        }
        String value = (String) client.get("value");
        if (!StringUtils.hasText(value)) {
                value = (String) client.get("name");
        }
        if (StringUtils.hasText(value)) {
                return value;
        }
        throw new IllegalStateException(...);
    }

    private static void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(LoadBalancerClientSpecification.class);
        builder.addConstructorArgValue(name);
        builder.addConstructorArgValue(configuration);
        registry.registerBeanDefinition(name + ".LoadBalancerClientSpecification", builder.getBeanDefinition());
	}

	@Override
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        Map<String, Object> attrs = metadata.getAnnotationAttributes(LoadBalancerClients.class.getName(), true);
        if (attrs != null && attrs.containsKey("value")) {
            AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value");
            for (AnnotationAttributes client : clients) {
                    registerClientConfiguration(registry, getClientName(client), client.get("configuration"));
            }
        }
        if (attrs != null && attrs.containsKey("defaultConfiguration")) {
            String name;
            if (metadata.hasEnclosingClass()) {
                    name = "default." + metadata.getEnclosingClassName();
            } else {
                    name = "default." + metadata.getClassName();
            }
            registerClientConfiguration(registry, name, attrs.get("defaultConfiguration"));
        }
        Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName(), true);
        String name = getClientName(client);
        if (name != null) {
            registerClientConfiguration(registry, name, client.get("configuration"));
        }
}
}

1.1.4 创建负载均衡器

LoadBalancer客户端工厂LoadBalancerClientFactory提供负载均衡各组件获取,大多场景是第一次使用客户端时进行初始化。

public class LoadBalancerClientFactory extends NamedContextFactory<LoadBalancerClientSpecification>
    implements ReactiveLoadBalancer.Factory<ServiceInstance> {
    public static final String NAMESPACE = "loadbalancer";
    public static final String PROPERTY_NAME = NAMESPACE + ".client.name";

    public LoadBalancerClientFactory() {
        super(LoadBalancerClientConfiguration.class, NAMESPACE, PROPERTY_NAME);
    }

    public String getName(Environment environment) {
        return environment.getProperty(PROPERTY_NAME);
    }

    @Override
    public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) {
        return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
    }
}

1.2 拦截器配置

LoadBalancer依赖spring-cloud-commons-xxx.jar提供自动配置类LoadBalancerAutoConfiguration,配置LoadBalancer公共服务全局默认组件。用于申明RestTemplateCustomizer封装拦截器LoadBalancerInterceptor注入RestTemplate组件。

Spring所有单例初始化后筛选SmartInitializingSingleton实例进行调用,主要调用入口就是IOC容器单实例初始化方法DefaultListableBeanFactory#preInstantiateSingleton

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
    @LoadBalanced
    @Autowired(required = false)
    private List<RestTemplate> restTemplates = Collections.emptyList();

    @Autowired(required = false)
    private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

    @Bean
    public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
        final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
        return () -> restTemplateCustomizers.ifAvailable(customizers -> {
            for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
                // 循环RestTemplateCustomizer初始化RestTemplate
                for (RestTemplateCustomizer customizer : customizers) {
                    customizer.customize(restTemplate);
                }
            }
        });
    }

    @Bean
    @ConditionalOnMissingBean
    public LoadBalancerRequestFactory loadBalancerRequestFactory(LoadBalancerClient loadBalancerClient) {
        return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers);
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
    static class LoadBalancerInterceptorConfig {
        // 负载均衡拦截器
        @Bean
        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);
            };
        }
    }
}

02 RestTemplate拦截器

LoadBalancer基于RestTemplate组件基础,通过扩展RestTemplate拦截器实现客户端服务发现、负载均衡功能,LoadBalancerInterceptor底层依赖LoadBalancerRequestFactory和LoadBalancerClient实现负载均衡。

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
    // 负载均衡
    private LoadBalancerClient loadBalancer;
    private LoadBalancerRequestFactory requestFactory;

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
        this.loadBalancer = loadBalancer;
        this.requestFactory = requestFactory;
    }

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
        this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
    }

    @Override
    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
                                        final ClientHttpRequestExecution execution) throws IOException {
        // URI
        final URI originalUri = request.getURI();
        // 服务名称=主机名称=域名
        String serviceName = originalUri.getHost();
        return loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
    }
}

2.1 创建请求

装饰器模式允许运行时动态添加新功能,而无需修改对象原始代码。所以,LoadBalancer拦截器也是采用装饰器模式增强请求行为,从而根据服务实例获取URL。

public class LoadBalancerRequestFactory {
    private LoadBalancerClient loadBalancer;
    private List<LoadBalancerRequestTransformer> transformers;

    public LoadBalancerRequestFactory(LoadBalancerClient loadBalancer,
                                      List<LoadBalancerRequestTransformer> transformers) {
        this.loadBalancer = loadBalancer;
        this.transformers = transformers;
    }

    public LoadBalancerRequest<ClientHttpResponse> createRequest(final HttpRequest request,
                                                                 final byte[] body, final ClientHttpRequestExecution execution) {
        return instance -> {
            HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance, this.loadBalancer);
            if (this.transformers != null) {
                for (LoadBalancerRequestTransformer transformer : this.transformers) {
                    serviceRequest = transformer.transformRequest(serviceRequest, instance);
                }
            }
            return execution.execute(serviceRequest, body);
        };
    }
}

2.2 发送请求

LoadBalancer负载均衡器客户端BlockingLoadBalancerClient发送请求,分为获取负载均衡器、选择负载均衡服务、执行请求发送三个步骤进行处理,负载均衡组件通过LoadBalancerRequestFactory提供。

public class BlockingLoadBalancerClient implements LoadBalancerClient {
    private final LoadBalancerClientFactory loadBalancerClientFactory;

    public BlockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {
        this.loadBalancerClientFactory = loadBalancerClientFactory;
    }

    @Override
    public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
        // 选择服务实例
        ServiceInstance serviceInstance = choose(serviceId);
        if (serviceInstance == null) {
            throw new IllegalStateException("No instances available for " + serviceId);
        }
        // 发送请求
        return execute(serviceId, serviceInstance, request);
    }

    @Override
    public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
        try {
            return request.apply(serviceInstance);
        } catch (IOException iOException) {
            throw iOException;
        } catch (Exception exception) {
            ReflectionUtils.rethrowRuntimeException(exception);
        }
        return null;
    }

    @Override
    public URI reconstructURI(ServiceInstance serviceInstance, URI original) {
        return LoadBalancerUriTools.reconstructURI(serviceInstance, original);
    }

    @Override
    public ServiceInstance choose(String serviceId) {
        // 获取负载均衡器
        ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);
        if (loadBalancer == null) {
            return null;
        }
        // 获取服务实例
        Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose()).block();
        if (loadBalancerResponse == null) {
            return null;
        }
        // 获取服务
        return loadBalancerResponse.getServer();
    }
}

03 负载均衡器

RibboLoadBalancern全局默认配置类LoadBalancerClientConfiguration,提供负载均衡器配置为RoundRobinLoadBalancer,负载均衡器主要提供服务选择核心功能。

public interface ReactorLoadBalancer<T> extends ReactiveLoadBalancer<T> {
    @SuppressWarnings("rawtypes")
    Mono<Response<T>> choose(Request request);
    // 选择服务
    default Mono<Response<T>> choose() {
        return choose(REQUEST);
    }
}

轮询负载均衡器使用ObjectProvider<ServiceInstanceListSupplier>获取服务,采用AtomicInteger与取模选取服务实例。

public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    private final AtomicInteger position;
    @Deprecated
    private ObjectProvider<ServiceInstanceSupplier> serviceInstanceSupplier;
    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;

    private final String serviceId;

    public RoundRobinLoadBalancer(
        ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
        String serviceId) {
        this(serviceInstanceListSupplierProvider, serviceId, new Random().nextInt(1000));
    }

    public RoundRobinLoadBalancer(
        ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
        String serviceId, int seedPosition) {
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        this.position = new AtomicInteger(seedPosition);
    }

    @Override
    @SuppressWarnings("rawtypes")
    // see original
    // https://github.com/Netflix/ocelli/blob/master/ocelli-core/
    // src/main/java/netflix/ocelli/loadbalancer/RoundRobinLoadBalancer.java
    public Mono<Response<ServiceInstance>> choose(Request request) {
        if (serviceInstanceListSupplierProvider != null) {
            ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
                .getIfAvailable(NoopServiceInstanceListSupplier::new);
            return supplier.get().next().map(this::getInstanceResponse);
        }
        ServiceInstanceSupplier supplier = this.serviceInstanceSupplier
            .getIfAvailable(NoopServiceInstanceSupplier::new);
        return supplier.get().collectList().map(this::getInstanceResponse);
    }

    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            return new EmptyResponse();
        }
        int pos = Math.abs(this.position.incrementAndGet());
        ServiceInstance instance = instances.get(pos % instances.size());
        return new DefaultResponse(instance);
    }

}