我们上篇已经知道PollingServerListUpdater有可能是负责与Eureka交互定时获取服务列表的,本篇我们就剖析下这个组件相关的逻辑。

1
2
3
class PollingServerListUpdater implements ServerListUpdater
private static long LISTOFSERVERS_CACHE_UPDATE_DELAY = 1000; // msecs;
private static int LISTOFSERVERS_CACHE_REPEAT_INTERVAL = 30 * 1000; // msecs;
  • LISTOFSERVERS_CACHE_UPDATE_DELAY
    服务列表缓存更新延时时间默认是1秒
  • LISTOFSERVERS_CACHE_REPEAT_INTERVAL
    服务列表更新间隔默认是30秒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class PollingServerListUpdater

@Override
public synchronized void start(final UpdateAction updateAction) {
final Runnable wrapperRunnable = new Runnable() {
@Override
public void run() {
// 这行代码就是拉取服务列表的核心逻辑
updateActiondoUpdate();
lastUpdated = SystemcurrentTimeMillis();
}
};

scheduledFuture = getRefreshExecutor()scheduleWithFixedDelay(
wrapperRunnable,
initialDelayMs,
refreshIntervalMs,
TimeUnitMILLISECONDS
);
}
  • updateActiondoUpdate
    通过引用分析,可以得到

    1
    2
    3
    4
    5
    6
    7
    8
    class DynamicServerListLoadBalancer

    protected final ServerListUpdaterUpdateAction updateAction = new ServerListUpdaterUpdateAction() {
    @Override
    public void doUpdate() {
    updateListOfServers();
    }
    };

    原来逻辑就是这个updateListOfServers()方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public 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初始化自动装配类的顺序有关。

    • 事实上,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
      26
      private 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

Comments