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中獲取註冊表 流程圖

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