聊聊ribbon源码解读(代码片段)

周杰伦本人 周杰伦本人     2022-12-02     698

关键词:

聊聊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实例中添加lanjie器LoadBalancerInterceptor,然后RestTemplate定制器RestTemplateCustomizer会向restTemplates集合中遍历每个restTemplate来添加lanjie器

lanjie器

那我们需要看一下LoadBalancerInterceptorlanjie器了,众所周知,lanjie器最重要的就是它的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);
  
  1. 获取负载均衡器
  2. 使用负载均衡器来选择最终要用的Server服务
  3. 把Server对象封装成RibbonServer
  4. 调用execute()来执行

接下来我们将重点分析下负载均衡器是如何定义的,负载均衡器是怎么选择服务器和execute()方法的逻辑是怎么样的

总结

这篇文章是Ribbon源码解读的第一篇,我们从springboot的自动装配的RibbonAutoConfiguration作为入口,分析了Ribbon是如果给RestTemplate添加LoadBalancerInterceptor lanjie器的,以及lanjie器的lanjie方法中调用RibbonLoadBalancerClient的execute(),接着分析了execute()方法中先获取lanjie器,再选择服务,然后执行execute()方法

聊聊ribbon获取服务列表和负载均衡策略(代码片段)

聊聊Ribbon获取服务列表和负载均衡策略在使用负载均衡器选取服务的时候是从所有的服务列表中获取的,那么服务列表是从哪里来的呢?服务列表的获取RibbonClientConfiguration中定义了ZoneAwareLoadBalancer负载均衡器,并使用了ServerList... 查看详情

ribbon源码载均衡算法(代码片段)

  负载均衡算法模块主要的功能是从负载均衡器中获取服务器列表信息,根据算法选取出一个服务器。IRule  负载均衡算法接口publicinterfaceIRulepublicServerchoose(Objectkey);//选择一个服务器publicvoidsetLoadBalancer(ILoadBalancerlb);//设置负... 查看详情

ribbon源码之client(代码片段)

  客户端模块的核心是提供便于用户操作的请求接口,并且实现了负载均衡功能。客户端模块的核心是IClient接口,定义了客户端网络请求的方法。publicinterfaceIClient<SextendsClientRequest,TextendsIResponse>publicTexecute(Srequest,IClientConf... 查看详情

ribbon源码之客户端(代码片段)

  客户端模块的核心功能是提供统一的用户请求操作接口。接口定义  客户端模块的核心是IClient接口,定义了客户端网络请求的方法。publicinterfaceIClient<SextendsClientRequest,TextendsIResponse>publicTexecute(Srequest,IClientConfigrequestCon... 查看详情

ribbon核心api源码解析:ribbon-coreiclient请求客户端-02(代码片段)

Ribbon核心API源码解析:ribbon-core(一)IClient请求客户端-02前言正文IClientClientRequestIResponse本地测试环境搭建配置key管理IClientConfigKeyCommonClientConfigKey示例总结前言上篇文章整体上对Ribbon做了介绍,可能有小伙伴的有... 查看详情

springmvc源码解读--handleradapter源码解读(代码片段)

 一路的继承关系来看的话因为实现了InitializingBean的话,然后该类首先可以调用的方法就是afterPropertiesSet  @Override publicvoidafterPropertiesSet() //Dothisfirst,itmayaddResponseBodyadvicebeans initControllerAdviceCache(); 查看详情

聊聊hystrix的源码(代码片段)

聊聊Hystrix的源码今天我们说一下Hystrix的源码的内容@EnableCircuitBreaker注解需要使用Hystrix的时候,需要我们通过@EnableCircuitBreaker来开启断路器,那么我们看一下这个注解:@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inheri... 查看详情

一起学源码-微服务ribbon源码一:ribbon概念理解及demo调试(代码片段)

...经梳理清楚了Eureka相关的概念及源码,接下来开始研究下Ribbon的实现原理。我们都知道Ribbon在springcloud中担当负载均衡的角色,当两个EurekaClient互相调用的时候,Ribbon能够做到调用时的负载,保证多节点的客户端均匀接收请求。(... 查看详情

一起学源码-微服务ribbon源码四:进一步探究ribbon的irule和iping(代码片段)

前言前情回顾上一讲深入的讲解了Ribbon的初始化过程及Ribbon与Eureka的整合代码,与Eureka整合的类就是DiscoveryEnableNIWSServerList,同时在DynamicServerListLoadBalancer中会调用PollingServerListUpdater进行定时更新Eureka注册表信息到BaseLoadBalancer中... 查看详情

springmvc源码解读--handlermapping代码解读(代码片段)

 AbstractHandlerMappingAbstractHandlerMapping这个类,在父类进行设置容器的时候,就会被调用到的。那么调用的是  /** *Initializestheinterceptors. *@see#extendInterceptors(java.util.List) *@see#initInterceptors() * 查看详情

springmvc源码解读--handleradapter源码解读(代码片段)

 一路的继承关系来看的话因为实现了InitializingBean的话,然后该类首先可以调用的方法就是afterPropertiesSet  @Override publicvoidafterPropertiesSet() //Dothisfirst,itmayaddResponseBodyadvicebeans initControllerAdviceCache(); if(this.argumentResolvers=... 查看详情

hashmap源码解读(代码片段)

HashMap源码解读在很多面试中,都会涉及到HashMap的问题,比如说问你HashMap存储结构,get、put的时间复杂度,或者扩容机制等等,这次我们来通过对源码的阅读,来实现对HashMap的理解!(大量源码源码警告!!!)先看类的继承... 查看详情

zookeeperzookeeper源码解读(代码片段)

...SnapShot4.网络通讯框架5.watcher监听机制1.概述视频:zookeeper源码解读2.序列化-反序列化这个接口跟hadoop的相关接口,很像。/***Interfacethatisimplementedbygeneratedclasses.**如果在zook 查看详情

fbkvocontroller源码使用及解读(代码片段)

源码地址:KVOController  系统标准KVO的使用-(void)viewDidLoad[superviewDidLoad];[self.personaddObserver:selfforKeyPath:@"name"options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNewcontext:n 查看详情

zookeeper源码解读(代码片段)

1.1. 客户端源码 1.1.1. 总体流程     启动客户端zkCli.sh文件里面的配置  实际运行  publicstaticvoidmain(Stringargs[])throwsKeeperException,IOException,InterruptedExcept 查看详情

hashmap源码解读(代码片段)

/***Thedefaultinitialcapacity-MUSTbeapoweroftwo.   *解释:为了节省空间和让元素均匀分布,所以初始化容量,需要为2的乘方。*/staticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;/***Theloadfactorusedwhennonespecifiedinconstructor.   *解释:默认的 查看详情

androidlayoutinflater源码解读(代码片段)

...是通过这个方式来设置布局的。虽然网络上已经有了很多源码解读的文章,但是我还是写了本篇文章,就是想要加深自己的理解和印象,只有在你真正一行一行的源码读 查看详情

vue源码解读预热-0(代码片段)

vueJS的源码解读vue源码总共包含约一万行代码量(包括注释)特别感谢作者EvanYou开放的源代码,访问地址为Github代码整体介绍与函数介绍预览代码模块分析代码整体思路总体的分析从图片中可以看出的为采用IIFE(Immedia... 查看详情