负载均衡:Ribbon源码剖析(2)维护服务列表
我们上篇已经知道PollingServerListUpdater
有可能是负责与Eureka交互定时获取服务列表的,本篇我们就剖析下这个组件相关的逻辑。
1 | class PollingServerListUpdater implements ServerListUpdater |
- LISTOFSERVERS_CACHE_UPDATE_DELAY
服务列表缓存更新延时时间默认是1秒 - LISTOFSERVERS_CACHE_REPEAT_INTERVAL
服务列表更新间隔默认是30秒
1 | class PollingServerListUpdater |
updateActiondoUpdate
通过引用分析,可以得到1
2
3
4
5
6
7
8class DynamicServerListLoadBalancer
protected final ServerListUpdaterUpdateAction updateAction = new ServerListUpdaterUpdateAction() {
public void doUpdate() {
updateListOfServers();
}
};原来逻辑就是这个
updateListOfServers()
方法1
2
3
4
5
6
7
8
9
10
11public void updateListOfServers() {
List<T> servers = new ArrayList<T>();
if (serverListImpl != null) {
servers = serverListImplgetUpdatedListOfServers();
if (filter != null) {
servers = filtergetFilteredListOfServers(servers);
}
}
updateAllServerList(servers);
}serverListImplgetUpdatedListOfServers
看到此处,笔者当时也是比较疑惑,因为上篇文章里的那个ConfigurationBasedServerList
并没有这个方法,在查找实现类后,笔者发现事情并不简单,经过一番debug后结论如下:- Spring提供的默认ServerList是
DomainExtractingServerList
- Spring提供的默认IPing是
NIWSDiscoveryPing
有兴趣的同学可以看一下
EurekaRibbonClientConfiguration
这个自动配置类,你会发现这里也声明了ribbon的核心组件。为了验证到底哪个会生效,可以分别对对应创建bean的方法打上断点debug一下,笔者上述结论就是这么得出的。顺便说一下,这和Spring初始化自动装配类的顺序有关。
- Spring提供的默认ServerList是
事实上,
serverListImplgetUpdatedListOfServers
最后调用的是DiscoveryEnabledNIWSServerList#obtainServersViaDiscovery
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26private List<DiscoveryEnabledServer> obtainServersViaDiscovery() {
List<DiscoveryEnabledServer> serverList = new ArrayList<DiscoveryEnabledServer>();
EurekaClient eurekaClient = eurekaClientProviderget();
if (vipAddresses!=null){
// vipAddresses
for (String vipAddress : vipAddressessplit(",")) {
List<InstanceInfo> listOfInstanceInfo = eurekaClientgetInstancesByVipAddress(vipAddress, isSecure, targetRegion);
for (InstanceInfo ii : listOfInstanceInfo) {
if (iigetStatus()equals(InstanceStatusUP)) {
if(shouldUseOverridePort){
InstanceInfo copy = new InstanceInfo(ii);
}
DiscoveryEnabledServer des = createServer(ii, isSecure, shouldUseIpAddr);
serverListadd(des);
}
}
if (serverListsize()>0 && prioritizeVipAddressBasedServers){
break;
}
}
}
return serverList;
}
此处的逻辑非常直观,就是根据vipAddress,也就是serverId、AppName,取出对应的服务实例列表,然后根据服务实例列表构造出Ribbon的`DiscoveryEnabledServer`
总结
- Spring通过一个
PollingServerListUpdater
定时任务每隔30秒,委托DiscoveryEnabledNIWSServerList
组件的obtainServersViaDiscovery
方法,从eureka client中拉取RibbonClient配置的服务对应的的服务器列表
正确的默认组件如下
Spring提供的默认ServerList是
DomainExtractingServerList
Spring提供的默认IPing是
NIWSDiscoveryPing
Spring提供的默认负载均衡器是
ZoneAwareLoadBalancer
Spring提供的默认负载均衡规则是
ZoneAvoidanceRule
Spring提供的默认RestClient是
OverrideRestClient
Spring定时更新服务列表的组件是
PollingServerListUpdater