work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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