springcloud ribbon 源码分析(6)——ribbon第一次从eureka获取到注册表之后后续如何持续更新呢?

eureka client自己本身,是不断的去从eureka server每隔30秒更新一次注册表,拉取增量注册表。所以说ribbon和eureka整合的机制里,肯定得有一个组件,负责每隔一定的时间,从本地的eureka client里刷新一下服务的注册表到LoadBalancer中。。。

 

 (1)调用PollingServerListUpdater实现类的start方法启动一个定时线程

public class DynamicServerListLoadBalancer<T extends Server> extends BaseLoadBalancer {

    /**
     * 实现了ServerListUpdater的UpdateAction()方法,直接调用updateListOfServers()来更新注册表
     * 其实就是从eureka client里去获取一下注册表,重新更新到LoadBalancer中去
     */
    protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
        @Override
        public void doUpdate() {
            updateListOfServers();
        }
    };

    void restOfInit(IClientConfig clientConfig) {
        boolean primeConnection = this.isEnablePrimingConnections();
        // turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()
        this.setEnablePrimingConnections(false);
        /**
         * 启动一个定时线程,每30s更新一次ServiceA的server list
         * 就去从eureka client刷新注册表到自己的ribbon的LoadBalancer中来
         */
        enableAndInitLearnNewServersFeature();

        //从eureka client那里获取到ServiceA的server list
        updateListOfServers();
        if (primeConnection && this.getPrimeConnections() != null) {
            this.getPrimeConnections()
                    .primeConnections(getReachableServers());
        }
        this.setEnablePrimingConnections(primeConnection);
        LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
    }

    public void enableAndInitLearnNewServersFeature() {
        LOGGER.info("Using serverListUpdater {}", serverListUpdater.getClass().getSimpleName());
        //调用PollingServerListUpdater实现类的start方法启动一个定时线程
        serverListUpdater.start(updateAction);
    }

    @VisibleForTesting
    public void updateListOfServers() {
        List<T> servers = new ArrayList<T>();
        if (serverListImpl != null) {
            //真正调用的是DiscoveryEnabledNIWSServerList实现类的getUpdatedListOfServers()方法
            servers = serverListImpl.getUpdatedListOfServers();
            LOGGER.debug("List of Servers for {} obtained from Discovery client: {}",
                    getIdentifier(), servers);

            if (filter != null) {
                //从一个服务中过滤掉某些server,不要去访问那些server
                servers = filter.getFilteredListOfServers(servers);
                LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}",
                        getIdentifier(), servers);
            }
        }
        //将从eurekaclient获取的servers列表设置进BaseLoadBalancer的服务实例列表allServerList,这将覆盖原有服务器列表。
        updateAllServerList(servers);
    }

}

 

(2)给PollingServerListUpdater的start()方法传入了一个UpdateAction,代表的是实际的更新注册表的行为。。。其实呢,每次PollingServerListUpdater定时更新注册表的时候,执行的实际的行为,就是上一篇博客看到的那个updateListOfServers()方法,其实就是从eureka client里去获取一下注册表,重新更新到LoadBalancer中去。。。。

在PollingServerListUpdater中,创建了一个Runnable线程,里面就是执行UpdateAction的行为。默认的是1秒钟过后,会第一次执行那个Runnable线程,以后是每隔30秒执行一下那个Runnable线程,就去从eureka client刷新注册表到自己的ribbon的LoadBalancer中来。

public class PollingServerListUpdater implements ServerListUpdater {

    @Override
    public synchronized void start(final UpdateAction updateAction) {
        if (isActive.compareAndSet(false, true)) {
            //创建了一个Runnable线程,里面就是执行UpdateAction的行为
            final Runnable wrapperRunnable = new Runnable() {
                @Override
                public void run() {
                    if (!isActive.get()) {
                        if (scheduledFuture != null) {
                            scheduledFuture.cancel(true);
                        }
                        return;
                    }
                    try {
                        /**
                         * updateAction其实是直接调用updateListOfServers()
                         * 其实就是从eureka client里去获取一下注册表,重新更新到LoadBalancer中去
                         */
                        updateAction.doUpdate();
                        lastUpdated = System.currentTimeMillis();
                    } catch (Exception e) {
                        logger.warn("Failed one update cycle", e);
                    }
                }
            };

            /**
             * 默认的是1秒钟过后,会第一次执行那个Runnable线程,以后是每隔30秒执行一下那个Runnable线程,
             * 就去从eureka client刷新注册表到自己的ribbon的LoadBalancer中来。
             */
            scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
                    wrapperRunnable,
                    initialDelayMs,
                    refreshIntervalMs,
                    TimeUnit.MILLISECONDS
            );
        } else {
            logger.info("Already active, no-op");
        }
    }
}

 

总结:ribbon如何持续的从eureka中获取注册表 流程图

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章