Make writing a habit together! This is the 13th day of my participation in the “Gold Digging Day New Plan · April More Text Challenge”. Click here for more details

Ribbon Service list updated

Constitute the determinants of genius should be diligent — Guo Moruo

How does the Ribbon get a registry example

Dynamic service load balancer DynamicServerListLoadBalancer

There is a restOfInit method in the load balancer, which involves pulling the list of services in the registry and pulling or listening for changes in the update list, which is then set up in the load balancer for service selection when the request is executed

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList
       
         serverList, ServerListFilter
        
          filter, ServerListUpdater serverListUpdater)
        
        {
    super(clientConfig, rule, ping);
    this.serverListImpl = serverList;
    this.filter = filter;
    this.serverListUpdater = serverListUpdater;
    if (filter instanceof AbstractServerListFilter) {
        ((AbstractServerListFilter) filter).
            setLoadBalancerStats(getLoadBalancerStats());
    }
    // Core methods, other methods are not carefully looked at first
    restOfInit(clientConfig);
}
Copy the code

EnableAndInitLearnNewServersFeature inside that this method is a core method, used for designated pull or to 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());
    }
Copy the code

Change operation enableAndInitLearnNewServersFeature service list

Enable notification of service list changes and updates

public void enableAndInitLearnNewServersFeature(a) {
    // The service list updater starts the updateAction update operation
    serverListUpdater.start(updateAction);
}
Copy the code
protected final ServerListUpdater.UpdateAction updateAction = 
        new ServerListUpdater.UpdateAction() {
    @Override
    public void doUpdate(a) {
        // This is the service instance pull operation described aboveupdateListOfServers(); }};Copy the code

Service list change policy

Timing pull policy

The ServerListUpdater. start method has two implementation strategies, one is the Eureka service notification operation, the other is the active pull service change operation, The default is PollingServerListUpdater update service policy [in RibbonClientConfiguration have created PollingServerListUpdater this strategy 】 the diagram below

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

Copy the code

Periodically pull the updated service list PollingServerListUpdater

30 seconds to pull the service list and check whether the service list has changed

private static long LISTOFSERVERS_CACHE_UPDATE_DELAY = 1000; // msecs;
// 30s to pull once
private static int LISTOFSERVERS_CACHE_REPEAT_INTERVAL = 30 * 1000; // msecs;


public PollingServerListUpdater(a) {
    this(LISTOFSERVERS_CACHE_UPDATE_DELAY, LISTOFSERVERS_CACHE_REPEAT_INTERVAL);
}
public PollingServerListUpdater(final long initialDelayMs, final long refreshIntervalMs) {
    this.initialDelayMs = initialDelayMs;
    this.refreshIntervalMs = refreshIntervalMs;
}
Copy the code

PollingServerListUpdater# start method

A thread scheduler called scheduledFuture was created to execute wrapperRunnable tasks with a fixed delay and frequency

@Override
public synchronized void start(final UpdateAction updateAction) {
    // Create a thread
    final Runnable wrapperRunnable = new Runnable() {
        @Override
        public void run(a) {
            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); }}};// The thread scheduler schedules wrapperRunnable tasks
    scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
            wrapperRunnable,
            initialDelayMs,
            refreshIntervalMs,
            TimeUnit.MILLISECONDS
    );

}
Copy the code

Updateaction.doupdate () updates the service list periodically

UpdateAction is before enableAndInitLearnNewServersFeature inside incoming updateAction () the method that is time to call updateListOfServers () method to update the service list

protected final ServerListUpdater.UpdateAction updateAction = new ServerListUpdater.UpdateAction() {
    @Override
    public void doUpdate(a) { updateListOfServers(); }};Copy the code

Service Listening policy

Eureka notification service list updater EurekaNotificationServerListUpdater

// Eureka event listener
private volatile EurekaEventListener updateListener;
// Eureka client
private volatile EurekaClient eurekaClient;

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

public EurekaNotificationServerListUpdater(final Provider<EurekaClient> 
                                eurekaClientProvider) {
    this(eurekaClientProvider, getDefaultRefreshExecutor());
}
// Construct the Eureka notification service list listener
public EurekaNotificationServerListUpdater(final Provider<EurekaClient>
            eurekaClientProvider, ExecutorService refreshExecutor) {
    this.eurekaClientProvider = eurekaClientProvider;
    this.refreshExecutor = refreshExecutor;
}
Copy the code

EurekaNotificationServerListUpdater# start method

public synchronized void start(final UpdateAction updateAction) {
if (isActive.compareAndSet(false.true)) {
    // Create a Eureka event listener
    this.updateListener = new EurekaEventListener() {
        @Override
    public void onEvent(EurekaEvent event) {
        // Cache refresh event
        if (event instanceof CacheRefreshedEvent) {
            if(! refreshExecutor.isShutdown()) { refreshExecutor.submit(new Runnable() {
                    @Override
                    public void run(a) {
                        try {
                            // Update the service list
                            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) {
        // Get the Eureka client
        eurekaClient = eurekaClientProvider.get();
    }
    if(eurekaClient ! =null) {
        // Register the listenereurekaClient.registerEventListener(updateListener); }}Copy the code

The updateAction.doupDate () method is the same as the previous one

summary

  1. There are two ways to update the service list
  2. One is a timed pull update list operation
  3. One is the Eureka cache refresh notification event to update the service list