Spring Cloud 负载均衡器 Ribbon实现原理(源码分析)
Posted on 2020-03-20 16:21 work hard work smart 阅读(307) 评论(0) 编辑 收藏 举报Ribbon核心工作原理
1、从前面Ribbon使用(应用间通信方式HTTP和RPC, 负载均衡器 Ribbion),只需要增加LoadBalanced就能实现负载均衡。进入LoadBalanced的源码
通过注解的注释,我们知道注解标注了RestTemplate作为负载均衡客户端。负载均衡客户端接口为LoadBalancerClient
2、进入LoadBalancerClient
/** * Represents a client-side load balancer. * * @author Spencer Gibb */ 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); }
LoadBalancerClient继承了ServiceInstanceChooser 接口
/** * Implemented by classes which use a load balancer to choose a server to send a request * to. */ public interface ServiceInstanceChooser { ServiceInstance choose(String serviceId); }
1) ServiceInstance choose(String serviceId); 该方法主要是根据负载均衡器选择一个服务实例
2)<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;
3)<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;
2) 和 3) 主要是为负载均衡器选择的服务执行请求
4)URI reconstructURI(ServiceInstance instance, URI original); 构建一个url,该方法主要使用具体逻辑服务名称作为host
3、LoadBalancerClient接口的实现类为LoadBalancerAutoConfiguration的内部类中
@Configuration( proxyBeanMethods = false ) @ConditionalOnClass({RestTemplate.class}) //当前环境有RestTemplate.class @ConditionalOnBean({LoadBalancerClient.class}) //当前环境需要由LoadBalancerClient接口的实现类 @EnableConfigurationProperties({LoadBalancerRetryProperties.class}) //初始化复制LoadBalancerRetryProperties public class LoadBalancerAutoConfiguration { @LoadBalanced @Autowired(required = false) //@AutoWired会自动装载集合类list,会将标注了@LoadBalanced(该注解被@Qualifier注解标注)的RestTemplate添加到restTemplates中 // private List<RestTemplate> restTemplates = Collections.emptyList(); @Autowired( required = false ) private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList(); public LoadBalancerAutoConfiguration() { } @Bean //SmartInitializingSingleton接口的实现类会在项目初始化之后被调用其afterSingletonsInstantiated方法 public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) { return () -> { restTemplateCustomizers.ifAvailable((customizers) -> { Iterator var2 = this.restTemplates.iterator(); while(var2.hasNext()) { RestTemplate restTemplate = (RestTemplate)var2.next(); Iterator var4 = customizers.iterator(); while(var4.hasNext()) { RestTemplateCustomizer customizer = (RestTemplateCustomizer)var4.next(); customizer.customize(restTemplate); } } }); }; } @Bean @ConditionalOnMissingBean //LoadBalancerRequestFactory被创建 public LoadBalancerRequestFactory loadBalancerRequestFactory(LoadBalancerClient loadBalancerClient) { return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers); } @Configuration( proxyBeanMethods = false ) @ConditionalOnClass({RetryTemplate.class}) public static class RetryInterceptorAutoConfiguration { public RetryInterceptorAutoConfiguration() { } @Bean @ConditionalOnMissingBean public RetryLoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties, LoadBalancerRequestFactory requestFactory, LoadBalancedRetryFactory loadBalancedRetryFactory) { return new RetryLoadBalancerInterceptor(loadBalancerClient, properties, requestFactory, loadBalancedRetryFactory); } @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer(final RetryLoadBalancerInterceptor loadBalancerInterceptor) { return (restTemplate) -> { List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } } @Configuration( proxyBeanMethods = false ) @ConditionalOnClass({RetryTemplate.class}) public static class RetryAutoConfiguration { public RetryAutoConfiguration() { } @Bean @ConditionalOnMissingBean public LoadBalancedRetryFactory loadBalancedRetryFactory() { return new LoadBalancedRetryFactory() { }; } } @Configuration( proxyBeanMethods = false ) @ConditionalOnMissingClass({"org.springframework.retry.support.RetryTemplate"}) static class LoadBalancerInterceptorConfig { LoadBalancerInterceptorConfig() { } @Bean //4、将loadBalancerClient接口的实现类和3方法中创建的LoadBalancerRequestFactory注入到该方法中 //同时成为LoadBalancerInterceptor的参数 public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) { return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); } @Bean @ConditionalOnMissingBean //5、方法4中创建的LoadBalancerInterceptor会被作为参数注入进来 public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) { return (restTemplate) -> { //5.1 这里会在afterSingletonsInstantiated()遍历调用 List<ClientHttpRequestInterceptor> list = new ArrayList(restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } } }
从注解中可以发现,当前类的加载时机必须存在restTemplate类,并且初始化了LoadBalancerClient的实现类。
其中LoadBalancerRequestFactory用于创建LoadBalancerRequest供LoaderBalancerInterceptor使用
LoadBalancerInterceptorConfig中维护了LoadBalancerInterceptor和RestTemplateCustomizer实例。
LoadBalancerInterceptor拦截每一次HTTP请求,将请求绑定进Ribbon负载均衡生命周期。
RestTemplateCustomizer为每个RestTemplate绑定LoadBalacerInterceptor
4、LoadBalacerInterceptor的源码如下:
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) { // for backwards compatibility this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer)); } @Override public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException { final URI originalUri = request.getURI(); String serviceName = originalUri.getHost(); Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri); //真正的执行方法 //loadBalancer类型为LoadBalancerClient,LoadBalancerClient默认实现类为RibbonLoadBalancerClient return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); } }
RibbonLoadBalancerClient的execute的源码如下
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException { return this.execute(serviceId, (LoadBalancerRequest)request, (Object)null); } public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException { //1、根据请求的serviceId来获取具体的LoadBalanced ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId); //获得具体server(包括哪台服务器和端口号) Server server = this.getServer(loadBalancer, hint); if (server == null) { throw new IllegalStateException("No instances available for " + serviceId); } else { //执行Http请求 RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server)); return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request); } } public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException { Server server = null; if (serviceInstance instanceof RibbonLoadBalancerClient.RibbonServer) { server = ((RibbonLoadBalancerClient.RibbonServer)serviceInstance).getServer(); } if (server == null) { throw new IllegalStateException("No instances available for " + serviceId); } else { RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId); RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server); try { T returnVal = request.apply(serviceInstance); statsRecorder.recordStats(returnVal); return returnVal; } catch (IOException var8) { statsRecorder.recordStats(var8); throw var8; } catch (Exception var9) { statsRecorder.recordStats(var9); ReflectionUtils.rethrowRuntimeException(var9); return null; } } }
1)首先得到一个ILoadBalancer 。ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
2)然后用它得到一个Server。 Server server = this.getServer(loadBalancer, hint);
protected Server getServer(ILoadBalancer loadBalancer, Object hint) { return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default"); }
3) ZoneAwareLoadBalancer的chooseServer的代码如下
public Server chooseServer(Object key) { if (this.counter == null) { this.counter = this.createCounter(); } this.counter.increment(); if (this.rule == null) { return null; } else { try { return this.rule.choose(key); } catch (Exception var3) { logger.warn("LoadBalancer [{}]: Error choosing server for key {}", new Object[]{this.name, key, var3}); return null; } } }
这里的 this.rule.choose(key);其实就是我们定义的IRule
作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!