聊聊Ribbon源码解读
聊聊Ribbon源码解读
要说当今最流行的组件当然是SpringCloud,要说框架中最流行的负载均衡组件,非Ribbon莫属了。随着用户量的逐渐增多,一台机器不足以支持用户的请求,这就需要多台机器来共同承当这个请求量,这就是需要负载均衡技术了
@LoadBalanced注解
当我们使用Ribbon的时候,spring中注入RestTemplate,并在上边添加 @LoadBalanced,这样使用RestTemplate发送请求的时候就实现了负载均衡
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
为什么会这样呢?今天我们分析一下它是什么工作的
配置文件
我们看一下Ribbon包下的spring.factories文件:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
配置类
这里显然自动装配了RibbonAutoConfiguration类,这就是入口了,我们深入这个类看一下,类上有个注解
@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})
表示RibbonAutoConfiguration加载后加载LoadBalancerAutoConfiguration和AsyncLoadBalancerAutoConfiguration
我们先看一下LoadBalancerAutoConfiguration类,LoadBalancerAutoConfiguration注入了RestTemplateCustomizer对象,并向RestTemplateCustomizer实例中添加拦截器LoadBalancerInterceptor,然后RestTemplate定制器RestTemplateCustomizer会向restTemplates集合中遍历每个restTemplate来添加拦截器
拦截器
那我们需要看一下LoadBalancerInterceptor拦截器了,众所周知,拦截器最重要的就是它的intercept()方法
@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);
return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
}
request.getURI()会获取到相应的url,originalUri.getHost()会拿到服务名,然后调用LoadBalancerClient的execute(),那么具体是哪个LoadBalancerClient实例呢,通过RibbonAutoConfiguration的bean定义我们知道:
@Bean
@ConditionalOnMissingBean(LoadBalancerClient.class)
public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient(springClientFactory());
}
是RibbonLoadBalancerClient,我们看一它的execute()方法
RibbonLoadBalancerClient
RibbonLoadBalancerClient的execute()方法
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
Server server = getServer(loadBalancer);
if (server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
}
RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
serviceId), serverIntrospector(serviceId).getMetadata(server));
return execute(serviceId, ribbonServer, request);
}
- 获取负载均衡器
- 使用负载均衡器来选择最终要用的Server服务
- 把Server对象封装成RibbonServer
- 调用execute()来执行
接下来我们将重点分析下负载均衡器是如何定义的,负载均衡器是怎么选择服务器和execute()方法的逻辑是怎么样的
总结
这篇文章是Ribbon源码解读的文章,我们从springboot的自动装配的RibbonAutoConfiguration作为入口,分析了Ribbon是如果给RestTemplate添加LoadBalancerInterceptor拦截器的,以及拦截器的拦截方法中调用RibbonLoadBalancerClient的execute(),接着分析了execute()方法中先获取拦截器,再选择服务,然后执行execute()方法
- 点赞
- 收藏
- 关注作者
评论(0)