在spring cloud与ribbon eureka集成过程中有两个涉及到ribbon的配置类Configuration按先后顺序为:RibbonAutoConfiguration,RibbonEurekaAutoConfiguration,下面我们从这两个类中分析ribbon是如何做负载均衡
1. RibbonAutoConfiguration
在这个配置主要的类为SpringClientFactory与LoadBalancerClient以及RibbonClientSpecification
- SpringClientFactory为按名称(实际为服务名称)定义Context子容器默认提供了RibbonClientConfiguration配置类
- RibbonClientSpecification为Context子容器提供Configuration的配置类,它是通过
@RibbonClients中RibbonClientConfigurationRegistrar注册类型为RibbonClientSpecification到BeanDefinitionMap - LoadBalancerClient实现了ServiceInstanceChooser通过服务名称获取服务的ServiceInstance,或者执行请求
2. RibbonEurekaAutoConfiguration
这个配置类主要是RibbonClients的执行,向bean容器中提供了关于eureka的对ribbon的配置EurekaRibbonClientConfiguration
3. 流程分析
image.png通过请求http://127.0.0.1:20000/list/instanceslb?service=service-user获取到通过规则的服务ServiceInstance 具体流程如下:
- ServiceInstanceChooser的具体实现类为RibbonLoadBalancerClient
- RibbonLoadBalancerClient从SpringClientFactory中获取类型为ILoadBalancer的bean,首次,是对于serveId的context容器还不存在,则会创建AnnotationConfigApplicationContext并将EurekaRibbonClientConfiguration和默认的RibbonClientConfiguration注册到BeanDefinitionMap,调用context.refresh();触发名称为’serviceId‘的容器进行初始化。context容器刷新之后获取到ILoadBalancer
- loadBalancer.chooseServer()获取Server然后包装为ServiceInstance(实现类为RibbonServer)
通过以上的分析我们可知道在做在对服务做负载均衡的时候对于每相同的spring.application.name的服务都会创建一个context子容器,通过该容器获取ILoadBalancer实现类选择得到的Server,那么内部的配置细节我们就得从子容器进行分析
4. 子容器context分析
初始化配置类为EurekaRibbonClientConfiguration和RibbonClientConfiguration,容器的父类是SpringBootApplication注解标识的启动类所在的容器,为什么EurekaRibbonClientConfiguration中的bean可以覆盖RibbonClientConfiguration中部分bean,原因1:EurekaRibbonClientConfiguration先注册到beanDefinitionNames(ArrayList)中且二者的bean定义中的attributes没有order属性不会进行重新排序,在ConfigurationClassPostProcessor处理的过程registry.getBeanDefinitionNames()依次处理,原因2:@ConditionalOnMissingBean的条件注解,在注册到beanDefinitionMap时会判断是否存在相同类型的bean定义,存在则跳过不注册.通过两个配置综合得到以下关键类
- ILoadBalancer 默认ZoneAwareLoadBalancer,可从配置PropertiesFactory获取
- IClientConfig 默认DefaultClientConfigImpl
- ServerList 默认:DomainExtractingServerList,可从配置PropertiesFactory获取
- ServerListFilter 默认:ZonePreferenceServerListFilter,可从配置PropertiesFactory获取
- IRule 默认:ZoneAvoidanceRule,可从配置PropertiesFactory获取
- IPing 默认:NIWSDiscoveryPing,可从配置PropertiesFactory获取
- ServerListUpdater 默认为PollingServerListUpdater
5.ILoadBalancer.chooseServer
- 服务列表的获取:在ZoneAwareLoadBalancer构造函数中执行restOfInit方法中调用updateListOfServers刷新服务列表(其中ServerListUpdater.start开启了定时任务定期执行updateListOfServers)
- updateListOfServers执行流程a:从DomainExtractingServerList获取通过Provider<EurekaClient>提供的EurekaClient拉取服务列表.b:对服务列表执行ServerListFilter 对列表进行过滤.c:设置allServerList,并对每个server的ServerStats进行初始化( 主要是对请求执行的情况做统计,可以为Irule提供数据).d:进行Iping将筛选的server放到upServerList并触发ServerStatusChange事件
- ILoadBalancer根据服务名称选择服务,启动调用了IRule 实现类对服务列表进行策略选择
注意:在restful服务中对于/list/exe接口中LoadBalancerRequest相当于回调方法,主要作用是执行拿到服务的ip后操作,供大家去进行扩展LoadBalancerClient封装ILoadBalancer 对于在feign中使用FeignLoadBalancer去包装了ILoadBalancer 最后也是在LoadBalancerContext#getServerFromLoadBalancer调用ILoadBalancer#chooseServer获取到服务:这也为我们如何在自己的项目里面集成ribbon提供了思路
网友评论