【SpringBoot】服务对注册中心的下线时机
1 前言
上节我们主要看了下服务启动的注册时机,可以看到它最后的落点是在实例化 DiscoveryClient 的时候进行服务的注册,看完启动注册,那么我们本节就看看当服务关闭时候的一个下线时机以及过程。
当然服务关闭也分情况,比如我能想到的直接暴力关闭类似 kill -9,柔和优雅关闭的类似 kill -15,我们本节主要看柔和关闭的情况。
2 下线时机
服务的下线时机,我看了下大概分为两个地方,但是都是由同一个入口进来的。
同一个入口就是我们 SpringBoot 服务启动的时候,刷新上下文里注册的关闭钩子函数,它会在 JVM 退出的时候,来得到执行。
两个地方:
(1)EurekaAutoServiceRegistration 实现了 SmartLifecycle 生命周期的接口,stop 方法会得到执行
(2)DiscoveryClient 的 destoryMethod = "shutdown" 销毁的时候得到执行
2.1 一个入口
// ###SpringApplication private void refreshContext(ConfigurableApplicationContext context) { // 上下文的刷新 refresh(context); // 注册关闭钩子 if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } } // ### AbstractApplicationContext @Override public void registerShutdownHook() { if (this.shutdownHook == null) { // No shutdown hook registered yet. this.shutdownHook = new Thread() { @Override public void run() { synchronized (startupShutdownMonitor) { doClose(); } } }; Runtime.getRuntime().addShutdownHook(this.shutdownHook); } } // ### protected void doClose() { // Check whether an actual close attempt is necessary... if (this.active.get() && this.closed.compareAndSet(false, true)) { if (logger.isDebugEnabled()) { logger.debug("Closing " + this); } if (!NativeDetector.inNativeImage()) { LiveBeansView.unregisterApplicationContext(this); } try { // 发布关闭事件 Publish shutdown event. publishEvent(new ContextClosedEvent(this)); } catch (Throwable ex) { logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); } // Stop all Lifecycle beans, to avoid delays during individual destruction. if (this.lifecycleProcessor != null) { try { // 两个地方之一 生命周期的关闭是在这里执行的 this.lifecycleProcessor.onClose(); } catch (Throwable ex) { logger.warn("Exception thrown from LifecycleProcessor on context close", ex); } } // 销毁bean Destroy all cached singletons in the context's BeanFactory. 两个地方之二 Bean的销毁是在这里执行的 destroyBeans(); // 关闭bean工厂 Close the state of this context itself. closeBeanFactory(); // 这里SpringBoot 用于关闭web容器比如停止掉tomcat Let subclasses do some final clean-up if they wish... onClose(); // Reset local application listeners to pre-refresh state. if (this.earlyApplicationListeners != null) { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Switch to inactive. this.active.set(false); } }
2.2 两个地方
(1)EurekaAutoServiceRegistration 实现了 SmartLifecycle 生命周期的接口,stop 方法会得到执行
// ### EurekaAutoServiceRegistration public void stop() { this.serviceRegistry.deregister(this.registration); this.running.set(false); }
(2)DiscoveryClient 的 destoryMethod = "shutdown" 销毁的时候得到执行
// ### CloudEurekaClient // public class CloudEurekaClient extends DiscoveryClient @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); }
日志信息:
最后画个图,捋一下思路:
3 小结
好啦,本节下线的时机就看到这里,有理解不对的地方欢迎指正。