Talk about shutdown of eurekclient

  springcloud

Order

This article mainly studies the shutdown of eureka client.

EurekaRegistration

spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar! /org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.java

    @Bean
    @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
    public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient, CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager, ObjectProvider<HealthCheckHandler> healthCheckHandler) {
        return EurekaRegistration.builder(instanceConfig)
                .with(applicationInfoManager)
                .with(eurekaClient)
                .with(healthCheckHandler)
                .build();
    }

    @Bean
    @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
    public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
        return new EurekaAutoServiceRegistration(context, registry, registration);
    }

    //...
    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
    public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {
        return new CloudEurekaClient(manager, config, this.optionalArgs,
                    this.context);
    }

EurekaRegistration is automatically created here, as well as EurekaAutoServiceRegistration, EurekaClient

EurekaClient

eureka-client-1.8.8-sources.jar! /com/netflix/discovery/EurekaClient.java

You can see that EurekaClient has marked @Bean(destroyMethod = “shutdown “), that is, when the bean is destroyed, the eurekaClient.shutdown method will be triggered.

EurekaRegistration

spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar! /org/springframework/cloud/netflix/eureka/serviceregistry/EurekaRegistration.java

public class EurekaRegistration implements Registration, Closeable {
    //......
    @Override
    public void close() throws IOException {
        this.eurekaClient.shutdown();
    }
}

The close method of the Closeable interface is implemented here, which is triggered when the spring container is closed. eurekaClient.shutdown () is called here

EurekaAutoServiceRegistration

spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar! /org/springframework/cloud/netflix/eureka/serviceregistry/EurekaAutoServiceRegistration.java

    @Override
    public void start() {
        // only set the port if the nonSecurePort or securePort is 0 and this.port != 0
        if (this.port.get() != 0) {
            if (this.registration.getNonSecurePort() == 0) {
                this.registration.setNonSecurePort(this.port.get());
            }

            if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
                this.registration.setSecurePort(this.port.get());
            }
        }

        // only initialize if nonSecurePort is greater than 0 and it isn't already running
        // because of containerPortInitializer below
        if (!this.running.get() && this.registration.getNonSecurePort() > 0) {

            this.serviceRegistry.register(this.registration);

            this.context.publishEvent(
                    new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig()));
            this.running.set(true);
        }
    }
    @Override
    public void stop() {
        this.serviceRegistry.deregister(this.registration);
        this.running.set(false);
    }

Here, start and stop implement the Lifecycle method, which will trigger the stop method when the spring container is closed, and then call service registry. deregister (this. registration)

RefreshScopeRefreshedEvent

spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar! /org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java

    @Configuration
    @ConditionalOnClass(RefreshScopeRefreshedEvent.class)
    protected static class EurekaClientConfigurationRefresher {

        @Autowired(required = false)
        private EurekaClient eurekaClient;

        @Autowired(required = false)
        private EurekaAutoServiceRegistration autoRegistration;

        @EventListener(RefreshScopeRefreshedEvent.class)
        public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
            //This will force the creation of the EurkaClient bean if not already created
            //to make sure the client will be reregistered after a refresh event
            if(eurekaClient != null) {
                eurekaClient.getApplications();
            }
            if (autoRegistration != null) {
                // register in case meta data changed
                this.autoRegistration.stop();
                this.autoRegistration.start();
            }
        }
    }

When receiving RefreshScopeRefreshedEvent, it will stop first and then start.

DiscoveryClient.shutdown

eureka-client-1.8.8-sources.jar! /com/netflix/discovery/DiscoveryClient.java

    public synchronized void shutdown() {
        if (isShutdown.compareAndSet(false, true)) {
            logger.info("Shutting down DiscoveryClient ...");

            if (statusChangeListener != null && applicationInfoManager != null) {
                applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId());
            }

            cancelScheduledTasks();

            // If APPINFO was registered
            if (applicationInfoManager != null
                    && clientConfig.shouldRegisterWithEureka()
                    && clientConfig.shouldUnregisterOnShutdown()) {
                applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
                unregister();
            }

            if (eurekaTransport != null) {
                eurekaTransport.shutdown();
            }

            heartbeatStalenessMonitor.shutdown();
            registryStalenessMonitor.shutdown();

            logger.info("Completed shut down of DiscoveryClient");
        }
    }

    /**
     * unregister w/ the eureka service.
     */
    void unregister() {
        // It can be null if shouldRegisterWithEureka == false
        if(eurekaTransport != null && eurekaTransport.registrationClient != null) {
            try {
                logger.info("Unregistering ...");
                EurekaHttpResponse<Void> httpResponse = eurekaTransport.registrationClient.cancel(instanceInfo.getAppName(), instanceInfo.getId());
                logger.info(PREFIX + "{} - deregister  status: {}", appPathIdentifier, httpResponse.getStatusCode());
            } catch (Exception e) {
                logger.error(PREFIX + "{} - de-registration failed{}", appPathIdentifier, e.getMessage(), e);
            }
        }
    }

As you can see here, first set the status to DOWN and then call the cancel method.

RestTemplateEurekaHttpClient

spring-cloud-netflix-eureka-client-2.0.0.RC1-sources.jar! /org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java

    public EurekaHttpResponse<Void> cancel(String appName, String id) {
        String urlPath = serviceUrl + "apps/" + appName + '/' + id;

        ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.DELETE,
                null, Void.class);

        return anEurekaHttpResponse(response.getStatusCodeValue())
                .headers(headersOf(response)).build();
    }

    @Override
    public EurekaHttpResponse<Void> register(InstanceInfo info) {
        String urlPath = serviceUrl + "apps/" + info.getAppName();

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);

        ResponseEntity<Void> response = restTemplate.exchange(urlPath, HttpMethod.POST,
                new HttpEntity<>(info, headers), Void.class);

        return anEurekaHttpResponse(response.getStatusCodeValue())
                .headers(headersOf(response)).build();
    }

The cancel method is to call REST’s DELETE operation to cancel the service.

Summary

Eureka packaged by springcloud is automatically registered, and is mainly divided into two categories when closed:

  • The dependent life cycle calls shutdown, close

The EurekaRegistration triggers the eurekaClient.shutdown method when close.
EurekaAutoServiceRegistration will mark the status as DOWN when stop and issue the StatusChangeEvent event.
EurekaClient has marked @Bean(destroyMethod = “shutdown “), that is, when the bean is destroyed, the eurekaClient.shutdown method will be triggered.

  • During the state change issue StatusChangeEvent event

Com/Netflix/Discovery/DiscoverClient.java has a StatusChangeListener. When the state changes are needed, the onDemandUpdate method of InstanceInfoReplicator will be triggered. The method will call discoveryClient.register () to update the state of its own instance with eureka server.
This is equivalent to changing the status status through the register interface in a disguised form.

Here, the difference between cancel and StatesChangeEvent should be distinguished. cancel deletes this instanceInfo from eureka server, while StatesChangeEvent changes the status, does not delete this instanceInfo, but only updates the status status (the status has up, down, starting, out _ of _ service, unknown and so on).

doc