The foreword 0.

  • Springboot version: 2.1.9.RELEASE
  • Springcloud version: Greenwich.SR4

1. Method entry

public class EurekaClientAutoConfiguration {
  
    @Configuration
    @ConditionalOnRefreshScope
    protected static class RefreshableEurekaClientConfiguration {
        / /...
        @Bean(destroyMethod = "shutdown")
        @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
	@org.springframework.cloud.context.config.annotation.RefreshScope
        @Lazy
        public EurekaClient eurekaClient(ApplicationInfoManager manager,
		EurekaClientConfig config, EurekaInstanceConfig instance,
	        @Autowired(required = false) HealthCheckHandler healthCheckHandler) {
            / /...
            // Step1: initialize CloudEurekaClient
	    CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager,
                    config, this.optionalArgs, this.context);
	    cloudEurekaClient.registerHealthCheck(healthCheckHandler);
	    returncloudEurekaClient; }}/ /...
}


// CloudEurekaClient.class
public CloudEurekaClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs
        args, ApplicationEventPublisher publisher) {
    // Step2: call the parent constructor
    super(applicationInfoManager, config, args);
    / /...
}


// DiscoveryClient.class
public DiscoveryClient(ApplicationInfoManager applicationInfoManager, final EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args) {
    this(...). ; }public DiscoveryClient(ApplicationInfoManager applicationInfoManager, final EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, EndpointRandomizer randomizer) {
    this(...). ; } DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {/ /...
    FetchRegistry ()
    if(clientConfig.shouldFetchRegistry() && ! fetchRegistry(false)) {
        // If the registry fails to be pulled from the server, the standby registry is obtained
        // The standby registry needs to be implemented by ourselves and configured through the configuration file
        // Select * from the registry.
        // 1. Obtain the value from the registry of the remote region
        // 2. The default registry is returned locally
        fetchRegistryFromBackup();
    }
    / /...
    // 3 Initializes the scheduled task, which contains the scheduled task for pulling registry information
    initScheduledTasks();
    / /...
}
Copy the code

2. fetchRegistry()

// DiscoveryClient.class
private boolean fetchRegistry(boolean forceFullRegistryFetch) {
    Stopwatch tracer = FETCH_REGISTRY_TIMER.start();

    try {
      // If the delta is disabled or if it is the first time, get all
      // applications
      Applications applications = getApplications();

        if(clientConfig.shouldDisableDelta() || (! Strings.isNullOrEmpty(clientConfig.getRegistryRefreshSingleVipAddress())) || forceFullRegistryFetch || (applications ==null)
                || (applications.getRegisteredApplications().size() == 0)
                || (applications.getVersion() == -1)) //Client application does not have latest library supporting delta
        {
            / /...
            // 2.1 Fully pull registry information
            getAndStoreFullRegistry();
        } else {
            // 2.2 Delta pull registry information
            getAndUpdateDelta(applications);
        }
        / /...
    } catch (Throwable e) {
        / /...
    } finally {
        / /...
    }
    / /...
}
Copy the code

2.1 Fully Pull registry information

// DiscoveryClient.class
private void getAndStoreFullRegistry(a) throws Throwable {
    long currentUpdateGeneration = fetchRegistryGeneration.get();

    logger.info("Getting all instance registry info from the eureka server");

    Applications apps = null;
    // Jersey requests server registry information
    // Registry -refresh- single-VIP-address is not configured in the configuration file, default is null, so call getApplications()
    EurekaHttpResponse<Applications> httpResponse = clientConfig.getRegistryRefreshSingleVipAddress() == null
            ? eurekaTransport.queryClient.getApplications(remoteRegionsRef.get())
            : eurekaTransport.queryClient.getVip(clientConfig.getRegistryRefreshSingleVipAddress(), remoteRegionsRef.get());
    if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
        apps = httpResponse.getEntity();
    }
    logger.info("The response status is {}", httpResponse.getStatusCode());

    if (apps == null) {
        logger.error("The application is null for some reason. Not storing this information");
    } else if (fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1)) {
        // The server returns that the registry information filtering is out of order and puts localRegionApps into the localRegionApps
        // Conditions for instances to be retained in the local registry:
        // 1. Instance status is UP (default)
        // 2. Region same as the current client instance
        localRegionApps.set(this.filterAndShuffle(apps));
        logger.debug("Got full registry with apps hashcode {}", apps.getAppsHashCode());
    } else {
        logger.warn("Not updating applications as another thread is updating it already"); }}Copy the code

2.2 Incrementally Pulling registry information

EurekaClient- A scheduled task initialized at startup

3. initScheduledTasks()

// DiscoveryClient.class
private void initScheduledTasks(a) {
    if (clientConfig.shouldFetchRegistry()) {
        // registry cache refresh timer
        int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
        int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
        // Start the periodic registry refresh task
        scheduler.schedule(
                new TimedSupervisorTask(
                        "cacheRefresh",
                        scheduler,
                        cacheRefreshExecutor,
                        registryFetchIntervalSeconds,
                        TimeUnit.SECONDS,
                        expBackOffBound,
                        // 3.1 Task threads
                        new CacheRefreshThread()
                ),
                registryFetchIntervalSeconds, TimeUnit.SECONDS);
    }
    / /...
}
Copy the code

3.1 CacheRefreshThread ()

// DiscoveryClient.class
class CacheRefreshThread implements Runnable {
    public void run(a) {
        // Refresh the registryrefreshRegistry(); }}@VisibleForTesting
void refreshRegistry(a) {
    try {
        / /...
        boolean remoteRegionsModified = false;
        / /...
        // 2 Pull the registry information from the server
        boolean success = fetchRegistry(remoteRegionsModified);
        / /...
    } catch (Throwable e) {
        logger.error("Cannot fetch registry from server", e); }}Copy the code

4. To summarize

  • Entry to pull up the registry: Refresh the registry task periodically when the client starts
  • How to pull the registry: full, incremental