ribbon源码

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Feign和Ribbon的工厂的层级结构,他们自己对于每个服务都有自己的小工厂,其父工厂是spring的大工厂,Feign是FeignContext,Ribbon是SpringClientFactory,两者都继承

NamedContextFactory,而在每个小工厂中,配置文件的读取顺序的优先级从高到低是:

1、服务对应的独享的configuration:@FeignClient配置最后生成FeignClientSpecification,形成name-configuration[]的配对,

Ribbon的话可以通过@RibbonClient或者@RibbonClients注解直接注册RibbonClientSpecification。

2、@EnableFeignClient和@RibbonClients中配置的defaultConfiguration(其实这两个注解也可以配置每个微服务单独对应的配置,不过一般用不到)

3、FeignContext和SpringClientFactory初始化的时候给父类NamedContextFactory传递的配置类FeignClientsConfiguration和RibbonClientSpecification
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Feign和ribbon的结合地方(以DefaultTargeter为例)在动态代理类(FeignInvocationHandler)发起请求--->MethodHandler(SynchronousMethodHandler).invoke--->client.execute。

这个client一路追踪上去,首先来自ParseHandlersByName中SynchronousMethodHandler.Factory类型的属性factory,再往上,是Feign.Builder的属性,默认是一个

new Client.Default,但是在FeignClientFactoryBean的getObject--->loadBalance方法中,会从Feign小工厂中找到一个LoadBalancerFeignClient并取代默认的Client,这个其实是spring

的大工厂中的,由FeignRibbonClientAutoConfiguration的@Bean方法注册,在org.springframework.cloud.netflix包的spring.factories中。

而LoadBalancerFeignClient的execute方法看下去,先用lbClient方法获取一个FeignLoadBalancer,调用的是CachingSpringLoadBalancerFactory的create方法,

CachingSpringLoadBalancerFactory的注册也是在FeignRibbonClientAutoConfiguration中,换句话说,也是在大工厂中,是全局的。

获取的FeignLoadBalancer是在3中的RibbonClientSpecification注册的ZoneAwareLoadBalancer,点进executeWithLoadBalancer看,LoadBalancerCommand是一个封装类,submit方法是一个RXJava的东西。

RXJava有单独的博文讲,这里不多说,因为不影响当前的逻辑,只是对请求结果的封装,server的选取涉及到负载均衡也放到下面讲,server获取到之后,发起请求用的是FeignLoadBalancer的execute方法

里面调用的是 request.client().execute,回头去看request是父类AbstractLoadBalancerfAwareClient的executeWithLoadBalancer方法传入的request的组装,在LoadBalancerFeignClient中,

request是一个封装类,request.client方法返回的是LoadBalancerFeignClient的delegate属性,回头看LoadBalancerFeignClient在@Bean方法中,发现是new Client.Default,点进去发现用的是HttpURLConnection,

可以看到默认的ConnectTimeout是2秒,ReadTimeout是5秒,前者是握手时长,后者是请求发出后到从监控端口读取返回的数据的时长,这两个数字是从哪里来的呢?

往上一层,是Client.Default.execute方法的参数,再往上,是FeignLoadBalancer的execute方法的参数,而这个参数又从IClientConfig来,再往上到AbstractLoadBalancerAwareClient的executeWithLoadBalancer

方法,在LoadBalancerFeignClient中,execute方法中的getClientConfig方法,点进去看,

如果是options是默认的options,从工厂中获取IClientConfig的实例,取代原来的options。这里通过途径3,RibbonClientConfiguration自己的小工厂注入,@bean方法中,

config.loadProperties--->loadDefaultValues,设置2秒和5秒,覆盖默认的10秒和60秒

如果不是默认的,说明是用户自定义的,那么就用用户自定义的Request.Options中的这两个属性。所以你如果觉得默认的5秒超时时间有点短,在微服务对应的feignclient的注解中configuration指向的配置类

(对应小工厂)中注册一个Request.Options即可(原理就是上面说的途径1覆盖途径3)。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
接着上面讲负载均衡策略,selectServer方法,loadBalancerContext.getServerFromLoadBalancer,ILoadBalancer.chooseServer方法

ILoadBalancer是3中注册的ZoneAwareLoadBalancer,其rule属性是3中的ZoneAvoidanceRule,serverList属性是2中的DiscoveryEnabledNIWSServerList(

RibbonEurekaAutoConfiguration有注解@RibbonClients(defaultConfiguration = EurekaRibbonClientConfiguration.class),这里的注解就是上面说到的微服务对应的小工厂途径2,在这个配置类里,

@Bean注解的ribbonServerList的方法返回DiscoveryEnabledNIWSServerList,其中参数有Provider<EurekaClient> eurekaClientProvider, Provider的原理和@lazy注解差不多,

在doResolveDependency方法前面会处理,返回一个动态代理类)。ZoneAwareLoadBalancer的父类DynamicServerListLoadBalancer构造方法中,ServerListUpdater属性会赋值一个

PollingServerListUpdater(一个定时任务),接着调用restOfInit方法,在这里启动定时任务,定时调用updateListOfServers--->eurekaClient.getInstancesByVipAddress方法,更新ZoneAwareLoadBalancer

对应的微服务的serverList,这里注意ZoneAwareLoadBalancer是由途径3注册的,每个微服务对应的小工厂里有一个,所以每一个balancer是知道自己属于哪个微服务的。

但是获取全量和增量的话是会获取到过期服务的,如果每次都获取全量,会把每个服务的leaseInfo带过来,可以知道最近一次该服务向注册中心注册是什么时候,

时间太远的说明服务不能使用了。但是现在是每次都获取增量,可以修改clientConfig.shouldDisableDelta的默认值为true,每次都获取全量。

猜你喜欢

转载自www.cnblogs.com/chuliang/p/11706681.html