背景 我看了一些介紹SpringBoot源碼的文章,里面都是從SpringApplication這個外部調用入口開始,重點介紹里面的listener監聽器。今天我想想說說SpringBoot的優雅退出機制。 調用入口調用SpringApplication開始啟動SpringBoot @SpringBootApplication public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
SpringApplication實例初始化時有以下操作 public SpringApplication(Object... sources) { this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.initialize(sources); }
其中有一步this.registerShutdownHook注冊jvm退出前的事件。 概念 jvm有shutdwonHook機制,中文習慣叫優雅退出。相當于在linux系統中執行SIGTERM(kill -15 或者 svc -d)時退出前執行的一些操作。 原理 以linux系統為例說明: 進程在響應kill -15 pid命令進行關閉操作時默認發送SIGTERM信號至指定進程/進程組。如果進程沒有捕獲該信號的邏輯,則SIGTERM的作用是終止進程。而registerShutdownHook=true說明有注冊的事件需要捕獲該信號,先執行相應的邏輯再進行終止。 /** * Register a shutdown hook with the JVM runtime, closing this context * on JVM shutdown unless it has already been closed at that time. * <p>Delegates to {@code doClose()} for the actual closing procedure. * @see Runtime#addShutdownHook * @see #close() * @see #doClose() */ @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); } }
如上面spring里registerShutdownHook的源碼所示,就是注冊一個jvm的shutdownHook鉤子函數。jvm退出前會執行這個鉤子函數。這個關閉操作在強制退出的時候不起作用。強制關閉范圍詳見下圖 
一個SpringBoot項目在優雅退出時做的事情可以通過log來感受一下 2019/06/20 20:47:20.405 Thread-29 [INFO] NettyHttpServer (NettyHttpServer.java:171) Close NettyHttpServer bind 0.0.0.0/0.0.0.0:5080
2019/06/20 20:47:20.405 Thread-36 [INFO] AnnotationConfigApplicationContext (AbstractApplicationContext.java:984) Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@a37aefe: startup date [Thu Jun 20 20:45:38 CST 2019]; root of context hierarchy
2019/06/20 20:47:20.406 Thread-32 [INFO] NettyServer (NettyServer.java:130) stopping netty server(XXX:9000), sleep 6 seconds!
2019/06/20 20:47:20.407 Thread-35 [INFO] ScheduleManager (ScheduleManager.java:373) Before taskNode quit,check executing task and callback result.
2019/06/20 20:47:20.407 Thread-35 [INFO] ScheduleManager (ScheduleManager.java:228) Destroy task node resources: zk and threadpool.
2019-06-20 20:47:20,430 Thread-35 WARN Unable to register Log4j shutdown hook because JVM is shutting down. Using SimpleLogger
總結 分析問題先找抓手
|