本文已参与「新人创作礼」活动,一起开启掘金创作之路。
RibbonLoadBalancerClient
LoadBalancerInterceptor
拦截器实际上是把请求交给LoadBalancerClient
,去执行实际的请求。
RibbonAutoConfiguraion
@Configuration
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
@RibbonClients
@AutoConfigureAfter(
name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,
AsyncLoadBalancerAutoConfiguration.class })
@EnableConfigurationProperties({ RibbonEagerLoadProperties.class,
ServerIntrospectorProperties.class })
RibbonAutoConfiguraion,在EurekaClientAutoConfiguration之后执行,也就是说eureka必须先初始化完。
RibbonAutoConfiguration,必须在LoadBalancerAutoConfiguration之前执行,LoadBalancerAutoConfiguration,是依赖于LoadBalancerClient的,但是LoadBalancerClient的初始化是在RibbonAutoConfiguration里执行的,所以必须是RibbonAutoConfiguraiton先执行,先初始化一个RibbonLoadBalancerClient才可以。
@Bean
@ConditionalOnMissingBean(LoadBalancerClient.class)
public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient(springClientFactory());
}
最终在LoadBalancerInterceptor拦截器里,会将RestTemplate的方法和请求转发给RibbonLoadBalancerClient.execute()方法去执行。
Ribbon完成服务请求的流程
RibbonLoadBalancerCient,负责进行请求的处理的。
serviceId:服务名称,ServiceA
- getLoadBalancer()方法,通过服务名称,获取了一个ILoadBalancer(负载均衡器)
- getServer()方法,通过ILoadBalancer对ServiceA对应的server list,通过自己的负载均衡的算法,选择一个server出来
- 构造RibbonServer对象。
- execute方法处理请求
DynamicServerListLoadBalancer:
Spring Cloud与Ribbon整合时的默认ILoadBalancer
RibbonLoadBalancerClient:如何创建ILoadBalancer,使用的是哪个ILoadBalancer?
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
根据serviceId(服务名),通过SpringClientFactory(继承NamedContextFactory)来获取对应的LoadBalancer的。
对Spring进行了一定程度上的封装,从Spring里面获取Bean的入口,都变成了这个Spring Cloud Ribbon自己的SpringClientFactory
SpringClientFactory对每个服务名称,都有一个对应的Spring的ApplicationContext容器,ServiceA对应着一个自己的独立的Spring的ApplicationContext容器
获取ServiceA服务的LoadBalancer,从ServiceA服务对应的ApplicationContext容器中去获取LoadBalancer。
name:ServiceA
type:ILoadBalancer接口
在SpringClientFactory里面,一个服务(比如说ServiceA),对应着一个独立的ApplicationContext,里面包含了这个服务的独立的一堆的组件,比如说LoadBalancer。如果要获取一个服务对应的LoadBalancer,其实就是在自己的那个ApplicationContext里面去获取那个LoadBalancer即可。根据ILoadBalancer接口类型,获取一个ILoadBalancer接口类型的实例化的bean即可。
RibbonClientConfiguration:在这个里面可以找到对应的ILoadBalancer的实例bean(ZoneAwareLoadBalancer)
ZoneAwareLoadBalancer,是在spring cloud整合ribbon的环境下,使用的默认的LoadBalancer
ZoneAwareLoadBalancer的父类是:DynamicServerListLoadBalancer,他的父类又是:BaseLoadBalancer
NamedContextFactory:根据名称去存储不同的 ApplicationContext,这样就能实现不同的名称的 Bean 隔离了。
流程
@LoadBalanced & RestTemplate
spring-cloud-commons.jar ->
LoadBalancerAutoConfiguration ->
SimartInitializingSingleton ->
RestTemplate(LoadBalancerClient & LoadBalancerRequest)
RestTemplateCustomer
<- LoadBalancerInterceptor
<- LoadBalancerClient & LoadBalancerRequestFactory(LoadBalancerClient & List<LoadBalancerRequestTransformer>)
LoadBalancerClient & RibbonLoadBalancerClient
Spring-Cloud-Netflix-Ribbon整合下LoadBalancerClient的实现类是RibbonLoadBalancerClient
ServiceInstanceChooser
:choose()
LoadBalancerClient
:execute()
:reconstructURI()
RibbonLoadBalancerClient
spring-cloud-netflix-ribbon.jar ->
RibbonAutoConfiguration ->
SpringClientFactory ->
RibbonLoadBalancerClient
RestTemplate请求经过LoadBalancerInterceptor拦截器,交由LoadBalancerClient处理。
LoadBalancerClient.execute()
1. 获取ILoadBalancer
2. 获取ServerList
3. 构造RibbonServer
ILoadBalancer & ZoneAwareLoadBalancer
spring-cloud-netflix-ribbon.jar ->
RibbonClientConfiguration(SpringClientFactory构造函数加载) ->
IClientConfig & ServerList<Server> & ServerListFilter<Server> & IRule & IPing & ServerListUpdater ->
ZoneAwareLoadBalancer
ZoneAwareLoadBalancer -> DynamicServerListLoadBalancer -> BaseLoadBalancer -> ILoadBalancer
ServerList & DomainExtractingServerList & DiscoveryEnabledNIWSServerList
装饰器:DomainExtractingServerList(DiscoveryEnabledNIWSServerList) -> ServerList
List<T> ServerList.getUpdatedListOfServers()
spring-cloud-netflix-eureka-client.jar ->
RibbonEurekaAutoConfiguration ->
@RibbonClients ->
EurekaRibbonClientConfiguration ->
DomainExtractingServerList(DiscoveryEnabledNIWSServerList)
日出在印象的港口来回光线唤醒了睡着的花叶
草地正为一场小雨欢悦我们彼此深爱这个世界
停在康桥上的那隻蝴蝶飞往午夜河畔的翡冷翠
遗憾被偶然藏在了诗页是微笑都透不进的世界