Netflix Ribbon - Ribbon负载均衡器自动装配

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


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

  1. getLoadBalancer()方法,通过服务名称,获取了一个ILoadBalancer(负载均衡器)
  2. getServer()方法,通过ILoadBalancer对ServiceA对应的server list,通过自己的负载均衡的算法,选择一个server出来
  3. 构造RibbonServer对象。
  4. execute方法处理请求

Spring-Cloud-Ribbon源码流程

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

image.png

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)

日出在印象的港口来回光线唤醒了睡着的花叶

草地正为一场小雨欢悦我们彼此深爱这个世界

停在康桥上的那隻蝴蝶飞往午夜河畔的翡冷翠

遗憾被偶然藏在了诗页是微笑都透不进的世界


猜你喜欢

转载自juejin.im/post/7117489533993615391
今日推荐