深入理解SpringCloud源码探究篇 | ribbon源码分析

SpringCloud系列:

  1. SpringCloud入门必看例子
  2. 深入理解SpringCloud源码探究篇 | Eureka服务端源码分析
  3. 深入理解SpringCloud源码探究篇 | Eureka客户端源码分析
  4. 深入理解SpringCloud源码探究篇 | ribbon源码分析
  5. 深入理解SpringCloud源码探究篇 | Feign源码分析

下面先利用白话文来描述下ribbon的工作流程

Ribbon:
    自动配置类RibbonClientConfigurationEurekaRibbonClientConfiguration配置类进行各bean转载包括以下五大组件和ZoneAwareLoadBalancer初始化操作
    五大组件:
        ServerList:定义获取服务器列表 ,默认实现DiscoveryEnabledNIWSServerList
        ServerListFilter:对ServerList服务器列表进行二次过滤 ,默认实现ZonePreferenceServerListFilter
        ServerListUpdater: 定义服务更新策略 ,默认实现PollingServerListUpdater
        IPing: 检查服务列表是否存活 默认实现NIWSDiscoveryPing
        IRule :根据算法中从服务列表中选取一个要访问的服务 ,默认实现RoundRobinRule
    ZoneAwareLoadBalancer: (ILoadBalancer默认的实现),ZoneAwareLoadBalancer是DynamicServerListLoadBalancer的子类,增加zone策略,DynamicServerListLoadBalancer对以上五大组件进行组合使用,调用ServerList接口,DiscoveryEnabledNIWSServerList(默认配置).getInitialListOfServers:从eureka客户端服务列表缓存中(DiscoveryClient.localRegionApps)获取服务列表 ;
    ServerListUpdater定义服务更新策略 (默认PollingServerListUpdater),这里DynamicServerListLoadBalancer初始化过程中会传入自己实现的ServerListUpdater.UpdateAction对象调用ServerListUpdater.start(UpdateAction)启动一个定时任务,任务中进程调用传入UpdateAction.doUpdate方法,实际调用的是DynamicServerListLoadBalancer.updateListOfServers方法然后调用ServerList的getUpdatedListOfServers方法进行服务拉取更新,接着updateListOfServers方法里拿到的服务列表之后会进行调用ServerListFilter的getFilteredListOfServers进行过滤筛选。总而言之就是DynamicServerListLoadBalancer初始化过程中会调用PollingServerListUpdater.start启动一个定时任务进行实时调用DiscoveryEnabledNIWSServerList.getUpdatedListOfServers去获DiscoveryClient里的服务列表缓存(DiscoveryClient.localRegionApps)取最新服务列表接着通过ServerListFilter进行过滤,然后将服务列表setServersList放在自己的缓存allServerList里(这个是BaseLoadBalancer的allServerList)。接着就是IRule :根据算法中从服务列表中选取一个要访问的服务 ,默认RoundRobinRule轮询算法。DynamicServerListLoadBalancer实现了ILoadBalancer的chooseServer方法,该实现方法里调用的就是IRule.choose,自然这里说的就是RoundRobinRule实现的方法choose,choose调用BaseLoadBalancer获取到服务缓存列表allServerList,然后进过一系列操作选择出一个调用的服务进行返回。 

以上提到的五大组件包括ILoadBalancer都是可以通过配置来进行自由选择实现类:

# 负载均衡类 
{服务名}.ribbon.NFLoadBalancerClassName=ZoneAwareLoadBalancer
# 负载均衡规则类
{服务名}.ribbon.NFLoadBalancerRuleClassName=AvailabilityFilteringRule
# 心跳检测类
{服务名}.ribbon.NFLoadBalancerPingClassName=NIWSDiscoveryPing
# 服务列表类
{服务名}.ribbon.NIWSServerListClassName=DiscoveryEnabledNIWSServerList
# 服务过滤类
{服务名}.ribbon.NIWSServerListFilterClassName=ZonePreferenceServerListFilter

 

RibbonClientConfiguration配置类

    @Bean
	@ConditionalOnMissingBean
	public IRule ribbonRule(IClientConfig config) {
		if (this.propertiesFactory.isSet(IRule.class, name)) {
			return this.propertiesFactory.get(IRule.class, config, name);
		}
		ZoneAvoidanceRule rule = new ZoneAvoidanceRule();
		rule.initWithNiwsConfig(config);
		return rule;
	}

	@Bean
	@ConditionalOnMissingBean
	public IPing ribbonPing(IClientConfig config) {
		if (this.propertiesFactory.isSet(IPing.class, name)) {
			return this.propertiesFactory.get(IPing.class, config, name);
		}
		return new DummyPing();
	}

	@Bean
	@ConditionalOnMissingBean
	@SuppressWarnings("unchecked")
	public ServerList<Server> ribbonServerList(IClientConfig config) {
		if (this.propertiesFactory.isSet(ServerList.class, name)) {
			return this.propertiesFactory.get(ServerList.class, config, name);
		}
		ConfigurationBasedServerList serverList = new ConfigurationBasedServerList();
		serverList.initWithNiwsConfig(config);
		return serverList;
	}

	@Bean
	@ConditionalOnMissingBean
	public ServerListUpdater ribbonServerListUpdater(IClientConfig config) {
		return new PollingServerListUpdater(config);
	}

	@Bean
	@ConditionalOnMissingBean
	public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
			ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
			IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
		if (this.propertiesFactory.isSet(ILoadBalancer.class, name)) {
			return this.propertiesFactory.get(ILoadBalancer.class, config, name);
		}
		return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList,
				serverListFilter, serverListUpdater);
	}

	@Bean
	@ConditionalOnMissingBean
	@SuppressWarnings("unchecked")
	public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
		if (this.propertiesFactory.isSet(ServerListFilter.class, name)) {
			return this.propertiesFactory.get(ServerListFilter.class, config, name);
		}
		ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
		filter.initWithNiwsConfig(config);
		return filter;
	}

EurekaRibbonClientConfiguration配置类

这两个配置类中我们可以发现初始化了ribbon的几大组件;这里我们可以看到先是从propertiesFactory配置中获取对应组件的自定义配置:

以上也证明我们前面提到的可以进行自定义配置个大组件的实现类

 

 ServerList接口

有两个方法,第一个为初始服务列表获取,第二个方法为更新缓存服务列表 

ServerList定义获取服务器列表 ,默认实现DiscoveryEnabledNIWSServerList:

这里两个实现方法均是调用obtainServersViaDiscovery方法进行服务列表拉取:

 通过调用DiscoveryClient.getInstancesByVipAddress获取InstanceInfo服务信息列表:

从上面的调用上可以看到,从 DiscoveryClient的localRegionApps缓存中获取到服务列表信息然后进行返回

 

ServerListFilter接口

仅提供一个方法 

ServerListFilter对ServerList服务器列表进行二次过滤 ,默认实现ZonePreferenceServerListFilter

 

ServerListUpdater接口

 

ServerListUpdater定义服务更新策略,默认实现PollingServerListUpdater:

实现start方法进行开启一个定时任务,目的就是刷新ribbon服务列表缓存

实际上调用的是传入的UpdateAction的doUpdate()方法,该方法在DynamicServerListLoadBalancer被实现重写,后面再描述

 

IRule接口

IRule根据算法从服务列表中选取一个要访问的服务 ,默认实现RoundRobinRule轮询:

以上可以清楚看到从ILoadBalancer的缓存列表allServerList里获取出所有的服务,然后进行轮询选择一个服务进行返回

 

ILoadBalancer

ILoadBalancer是ribbon整个的核心,相当于一个中央控制器,默认实现ZoneAwareLoadBalancer:

ZoneAwareLoadBalancer是DynamicServerListLoadBalancer的子类,增加zone策略,DynamicServerListLoadBalancer对以上五大组件进行组合使用:

我们先来看DynamicServerListLoadBalancer该类被初始化是做了哪些具体操作:

其他的操作均是将五大组件bean赋值于DynamicServerListLoadBalancer中,我们重点来看看restOfInit:

该方法调用enableAndInitLearnNewServersFeature以及updateListOfServers,我们先看enableAndInitLearnNewServersFeature:

这里我们可以清楚看到它调用了ServerListUpdater的start方法,start我们前面已经讲到就是启动了一个定时任务,具体操作线程我们需要看这个传入的UpdateAction的具体实现,DynamicServerListLoadBalancer实现了ServerListUpdater.UpdateAction:

然后doUpdate实际调用的是自己的updateListOfServers方法:

以上可以清楚看到利用ServerList的实现DiscoveryEnabledNIWSServerList调用getUpdatedListOfServers,该方法前面已经分析过,就是向eureka客户端的localRegionApps缓存进行服务的拉取操作然后返回服务列表。

接着调用ServerListFilter的实现进行二次过滤,这里我就不具体分析这个了。接着就是调用updateAllServerList(servers),然后接着setServersList对服务列表放入进BaseLoadBalancer的allServerList里

到这里也就是说DynamicServerListLoadBalancer初始化过程中调用ServerListUpdater.start方法进行启动一个定时任务来调用updateListOfServers方法,进行服务拉取操作以及过滤。我们回到restOfInit方法启动任务之后接着下一步还是调用updateListOfServers,其实就是一起动就去拉取服务列表。总而言之就是初始化过程进行服务拉取进自己的allServerList缓存列表中,然后定时进行服务拉取更新操作。

ILoadBalancer的对外提供中比较主要的就是chooseServer方法,用来服务挑选,我们直接看DynamicServerListLoadBalancer的父类BaseLoadBalancer的chooseServer方法:

以上可以看到利用IRule实现的choose进行服务挑选,前面初始化时已经将其实现类RoundRobinRule赋值了进来,前面也已经提到过RoundRobinRule的choose方法,这里不再赘述。

 

总结

ILoadBalancer被默认初始化ZoneAwareLoadBalancer,然后接着进行向eureka客户端的localRegionApps缓存中获取服务列表接着过滤后放入自己的缓存allServerList里。接着调用ServerListUpdater.start启动一个定时任务进行服务的拉取更新操作和过滤。在对外提供使用过程中调用chooseServer方法进行调用IRule的choose方法进行服务的挑选和具体服务返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值