简介
Ribbon 是netflix 公司开源的基于客户端的负载均衡组件,是Spring Cloud大家庭中非常重要的一个模块。
原理
正常Ribbon在Spring Cloud中是和Feign 一起配合使用的,Ribbon负责负载均衡,Feign在执行具体的请求,Feign的底层会通过Ribbon来实现负载均衡。
看底层源码的时候是直接用了Ribbon的一个注解来注解RestTemplate,这个注解@LoadBalanced,以这个注解为切入点看下他的底层原理
1.扫描注释的对象,从配置类入手:在spring cloud commons 项目下的 loadbalancer包下 有一个LoadBalancerAutoConfiguration 配置类,其实很多注解 就是通过Spring 一些对应的configuration去扫描对应注解然后对这个对象进行业务增强或者添加拦截器 来实现底层逻辑
2.LoadBalancerInterceptor 给注释对象增加拦截器: 寻找到LoadBalancerAutoConfiguration配置,其中一个方法初始化的时候 对有注解@LoadBalanced的对象定制化了拦截器(LoadBalancerInterceptor),拦截器实例化的时候 通过构造器传入了LoadBalancerClient(到处没找到LoadBalancerClient,后面才发现应该是在别的地方,对这个实现类构造了一个实例,然后打成了一个@Bean,这里才可以注入 ,源码的使用方法是该类上使用了@ConditionalOnBean(LoadBalancerClient.class) 指明必须 LoadBalancerClient 初始化了才开始加载,然后在这个类的方法里面初始化LoadBalancerInterceptor 这个bean,这个时候它的构造函数 传入LoadBalancerClient 才会有这个对象。 RibbonAutoConfiguration 配置类 中 初始化了 LoadBalancerClient)
3.拦截请求交给LoadBalancerClient处理:RestTemplate执行请求的时候 会被 LoadBalancerInterceptor 拦截,从你的url地址里获取hostname作为服务名称然后交给LoadBalancerClient.execute() -- 获取对应的ILoadBalancer
4.ILoadBalancer(接口)初始化(其实就是ZoneAwareLoadBalancer)(构造参数ServerListUpdater(PollingServerListUpdater) :另外一个bean初始化了它): (通过ILoadBalancer负载均衡根据服务名去注册表中根据负载均衡算法获取server)
ILoadBalancer其实就是ZoneAwareLoadBalancer初始化(ILoadBalancer初始化 中 实例化 ) ZoneAwareLoadBalancer父类是DynamicServerListLoadBalancer ,DynamicServerListLoadBalancer父类是ILoadBalancer。
总结:ILoadBalancer初始化 就是初始化的ZoneAwareLoadBalancer 子类
5.DynamicServerListLoadBalancer内部 restOfInit 启动PollingServerListUpdater定时器30S跑一次-- updateListOfServers --- serverListImpl.getUpdatedListOfServers() -- DomainExtractingServerList.getUpdatedListOfServers() --- DiscoveryEnabledNIWSServerList.obtainServersViaDiscovery 去EurekaClient 获取更新注册表 server list 保存在BaseLoadBalancer
总结:ZoneAwareLoadBalancer组件 构造时 启动PollingServerListUpdater定时器30S跑一次 通过DiscoveryEnabledNIWSServerList 向 EurekaClient 获取更新注册表 server list 保存在BaseLoadBalancer (ILoadBalancer父类)
6.ZoneAwareLoadBalancer先选一个机房zone,然后根据IRule组件选择轮询算法选择一个server,然后重构url地址
总结:
0.启动服务的时候spring 会去初始化bean,ILoadBalancer组件(ZoneAwareLoadBalancer(在父类BaseLoadBalancer 初始化好IRule 负载均衡组件))放到了spring 容器中,ZoneAwareLoadBalancer 开启了PollingServerListUpdater定时任务 每30S会
调用DiscoveryEnabledNIWSServerList 向EurekaClient 获取更新注册表 server list 保存在BaseLoadBalancer 父类里面
1.@LoadBalanced 注释的对象行为 会被LoadBalancerInterceptor 拦截 交给 LoadBalancerClient 执行
2.LoadBalancerClient 会根据服务名称从spring 容器获取ILoadBalancer组件, ZoneAwareLoadBalancer 会根据 IRule 负责均衡算法组件 ,让这个组件去从server list 负载均衡 获取server
3.重构请求地址url 然后发送请求
原理流程图:
bean 初始化 关系图:
执行流程图
配置优化:
ribbon:
ConnectTimeout: 3000
ReadTimeout: 3000
OkToRetryOnAllOperations: true
MaxAutoRetries: 1 重试一次
MaxAutoRetriesNextServer: 1