Diagram + source code to explain Ribbon service list update

Get into the habit of writing together! This is the 13th day of my participation in the "Nuggets Daily New Plan·April Update Challenge", click to view the event details

Diagram + source code to explain Ribbon service list update

Diligence is the decisive factor for genius - Guo Moruo

Related Articles
Illustration + Source Code Explaining Ribbon How to Get the Registration Center Example
Illustration + Source Code Explaining Ribbon Principles

Dynamic Service Load Balancer DynamicServerListLoadBalancer

    There is a restOfInit method in this load balancer. This method involves pulling the service list of the registry, and pulling or monitoring the changes of the update list, and then setting it in the load balancer and providing it to the request execution time. Make a service selection

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule,
    IPing ping, ServerList<T> serverList, ServerListFilter<T> filter,
    ServerListUpdater serverListUpdater) {
    super(clientConfig, rule, ping);
    this.serverListImpl = serverList;
    this.filter = filter;
    this.serverListUpdater = serverListUpdater;
    if (filter instanceof AbstractServerListFilter) {
        ((AbstractServerListFilter) filter).
            setLoadBalancerStats(getLoadBalancerStats());
    }
    // 核心方法,其他的方法先不细看
    restOfInit(clientConfig);
}
复制代码

    In this method, enableAndInitLearnNewServersFeature is a core method used to perform specified pull or monitor service change list

    void restOfInit(IClientConfig clientConfig) {
        boolean primeConnection = this.isEnablePrimingConnections();
        // turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()
        this.setEnablePrimingConnections(false);
        enableAndInitLearnNewServersFeature();

        updateListOfServers();
        if (primeConnection && this.getPrimeConnections() != null) {
            this.getPrimeConnections()
                    .primeConnections(getReachableServers());
        }
        this.setEnablePrimingConnections(primeConnection);
        LOGGER.info("DynamicServerListLoadBalancer for client {} initialized: {}", clientConfig.getClientName(), this.toString());
    }
复制代码

Service list change operation enableAndInitLearnNewServersFeature

    Enable service list change update notification operation

public void enableAndInitLearnNewServersFeature() {
    // 服务列表更新器开启 updateAction 更新操作
    serverListUpdater.start(updateAction);
}
复制代码
protected final ServerListUpdater.UpdateAction updateAction = 
        new ServerListUpdater.UpdateAction() {
    @Override
    public void doUpdate() {
        // 这个就是上面讲解的服务实例拉取操作
        updateListOfServers();
    }
};
复制代码

Service List Change Policy

Timed pull strategy

    The serverListUpdater.start method has two implementation strategies, one is eureka service notification operation, the other is active pull service change operation, the default is PollingServerListUpdater update service strategy [PollingServerListUpdater strategy has been created in RibbonClientConfiguration] as shown below
image.png

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

复制代码

image.png

Regularly pull the updated service list PollingServerListUpdater

    30s to pull the service list once to see if the service list has changed

private static long LISTOFSERVERS_CACHE_UPDATE_DELAY = 1000; // msecs;
// 30s 去拉取一次
private static int LISTOFSERVERS_CACHE_REPEAT_INTERVAL = 30 * 1000; // msecs;


public PollingServerListUpdater() {
    this(LISTOFSERVERS_CACHE_UPDATE_DELAY, LISTOFSERVERS_CACHE_REPEAT_INTERVAL);
}
public PollingServerListUpdater(final long initialDelayMs, final long refreshIntervalMs) {
    this.initialDelayMs = initialDelayMs;
    this.refreshIntervalMs = refreshIntervalMs;
}
复制代码

PollingServerListUpdater#start 方法

    Created a thread scheduler scheduledFuture to execute the wrapperRunnable task with a fixed delay and frequency

@Override
public synchronized void start(final UpdateAction updateAction) {
    // 创建一个线程
    final Runnable wrapperRunnable = new Runnable() {
        @Override
        public void run() {
            if (!isActive.get()) {
                if (scheduledFuture != null) {
                    scheduledFuture.cancel(true);
                }
                return;
            }
            try {
                updateAction.doUpdate();
                lastUpdated = System.currentTimeMillis();
            } catch (Exception e) {
                logger.warn("Failed one update cycle", e);
            }
        }
    };
    // 线程调度器调度 wrapperRunnable 任务
    scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
            wrapperRunnable,
            initialDelayMs,
            refreshIntervalMs,
            TimeUnit.MILLISECONDS
    );

}
复制代码

updateAction.doUpdate() regularly updates the service list

    updateAction is the UpdateAction passed in the previous enableAndInitLearnNewServersFeature() method. In fact, it is to call the updateListOfServers() method regularly to update the service list.

protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
    @Override
    public void doUpdate() {
        updateListOfServers();
    }
};
复制代码

Service monitoring strategy

Eureka Notification Service List Updater EurekaNotificationServerListUpdater

// eureka事件监听器
private volatile EurekaEventListener updateListener;
// eureka 客户端
private volatile EurekaClient eurekaClient;

public EurekaNotificationServerListUpdater() {
    this(new LegacyEurekaClientProvider());
}

public EurekaNotificationServerListUpdater(final Provider<EurekaClient> 
                                eurekaClientProvider) {
    this(eurekaClientProvider, getDefaultRefreshExecutor());
}
// 构造 eureka通知服务列表监听器
public EurekaNotificationServerListUpdater(final Provider<EurekaClient>
            eurekaClientProvider, ExecutorService refreshExecutor) {
    this.eurekaClientProvider = eurekaClientProvider;
    this.refreshExecutor = refreshExecutor;
}
复制代码

EurekaNotificationServerListUpdater#start 方法

public synchronized void start(final UpdateAction updateAction) {
if (isActive.compareAndSet(false, true)) {
    // 创建了一个eureka事件监听器
    this.updateListener = new EurekaEventListener() {
        @Override
    public void onEvent(EurekaEvent event) {
        // 缓存刷新事件
        if (event instanceof CacheRefreshedEvent) {
            if (!refreshExecutor.isShutdown()) {
                refreshExecutor.submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            // 进行服务列表更新
                            updateAction.doUpdate();
                            lastUpdated.set(System.currentTimeMillis());
                        } catch (Exception e) {
                            logger.warn("Failed to update serverList", e);
                        } finally {
                            updateQueued.set(false);
                        }
                    }
                });
            }
            else {
                stop();
            }
        }
    }
    };
    if (eurekaClient == null) {
        // 获取 eureka 客户端 
        eurekaClient = eurekaClientProvider.get();
    }
    if (eurekaClient != null) {
        // 注册监听器
        eurekaClient.registerEventListener(updateListener);
    } 
}
复制代码

updateAction.doUpdate() This method is the same as the follow-up above

summary

  1. Two ways to update the service list
  2. One is to periodically pull and update the list operation
  3. One is the eureka cache refresh notification event to update the service list

Guess you like

Origin juejin.im/post/7085892529186406430