一文帶你了解SpringBoot的停機方式
1. 介紹
簡單的說,就是向應(yīng)用進程發(fā)出停止指令之后,能保證正在執(zhí)行的業(yè)務(wù)操作不受影響,直到操作運行完畢之后再停止服務(wù)。應(yīng)用程序接收到停止指令之后,會進行如下操作:
1.停止接收新的訪問請求
2.正在處理的請求,等待請求處理完畢;對于內(nèi)部正在執(zhí)行的其他任務(wù),比如定時任務(wù)、mq 消費等等,也要等當(dāng)前正在執(zhí)行的任務(wù)執(zhí)行完畢,并且不再啟動新的任務(wù)
3.當(dāng)應(yīng)用準備關(guān)閉的時候,按需向外發(fā)出信號,告知其他應(yīng)用服務(wù)準備接手,以保證服務(wù)高可用
如果暴力的關(guān)閉應(yīng)用程序,比如通過kill -9 命令強制直接關(guān)閉應(yīng)用程序進程,可能會導(dǎo)致正在執(zhí)行的任務(wù)數(shù)據(jù)丟失或者錯亂,也可能會導(dǎo)致任務(wù)所持有的全局資源等不到釋放,比如當(dāng)前任務(wù)持有 redis 的鎖,并且沒有設(shè)置過期時間,當(dāng)任務(wù)突然被終止并且沒有主動釋放鎖,會導(dǎo)致其他進程因無法獲取鎖而不能處理業(yè)務(wù)。
那么如何在不影響正在執(zhí)行的業(yè)務(wù)的情況下,將應(yīng)用程序安全的進行關(guān)閉呢?
2. 停機方式
2.1 使用ApplicationContext的close方法關(guān)閉服務(wù)
可以使用ApplicationContext的close方法來關(guān)停服務(wù),他會自動銷毀bean對象并關(guān)停服務(wù)
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//啟動10秒以后,自動關(guān)閉
context.close();
}
}
2.2 使用SpringApplication的exit方法關(guān)閉服務(wù)
通過調(diào)用一個SpringApplication.exit()方法也可以安全的退出程序,同時會返回一個退出碼,這個退出碼可以傳遞給所有的context,最后通過調(diào)用System.exit()可以將這個錯誤碼也傳給JVM。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
//5秒后,關(guān)閉服務(wù)
exitApplication(context);
}
public static void exitApplication(ConfigurableApplicationContext context) {
//獲取退出碼
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
//退出碼傳遞給jvm,安全退出程序
System.exit(exitCode);
}
}
3. 停機處理
3.1 DisposableBean
SpringBoot 官方文檔上,已經(jīng)告訴開發(fā)者只需要實現(xiàn)特定接口即可監(jiān)聽到項目啟動成功與關(guān)閉時的事件,相關(guān)接口如下:
CommandLineRunner接口:當(dāng)應(yīng)用啟動成功后但在開始接受流量之前,會回調(diào)此接口的實現(xiàn)類,也可以實現(xiàn)ApplicationRunner接口,工作的方式與CommandLineRunner與之類似
DisposableBean接口:當(dāng)應(yīng)用正要被銷毀前,會回調(diào)此接口的實現(xiàn)類,也可以使用@PreDestroy注解,被標記的方法也會被調(diào)用
基于此流程,我們可以創(chuàng)建一個服務(wù)監(jiān)聽類,用于監(jiān)聽到項目啟動成功與關(guān)閉時的回調(diào)服務(wù),示例代碼如下:
@Component
public class AppListener implements CommandLineRunner, DisposableBean {
@Override
public void run(String... args) throws Exception {
System.out.println("應(yīng)用啟動成功,預(yù)加載相關(guān)數(shù)據(jù)");
}
@Override
public void destroy() throws Exception {
System.out.println("應(yīng)用正在關(guān)閉,清理相關(guān)數(shù)據(jù)");
}
}
3.2 PreDestroy
上文中,我們提到了實現(xiàn)DisposableBean接口,可以監(jiān)聽?wèi)?yīng)用關(guān)閉前的回調(diào)處理,其實在自定義的方法上加@PreDestroy注解,也可以實現(xiàn)相同的效果。
@Component
public class AppDestroyConfig {
@PreDestroy
public void PreDestroy(){
System.out.println("應(yīng)用程序正在關(guān)閉。。。");
}
}
3.3 ApplicationListener
如果有些服務(wù),比如定時任務(wù),我們想在SpringBoot關(guān)閉數(shù)據(jù)源連接池之前,將其關(guān)閉,可以通過實現(xiàn)ApplicationListener接口,監(jiān)聽bean對象的變化情況,在bean對象銷毀之前,執(zhí)行相關(guān)的關(guān)閉任務(wù)。
@Component
public class JobTaskListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
// 在spring bean容器銷毀之前執(zhí)行的事件,防止數(shù)據(jù)庫連接池在任務(wù)終止前銷毀
if (applicationEvent instanceof ContextClosedEvent) {
System.out.println("關(guān)閉相關(guān)的定時任務(wù)");
}
}
}
到此這篇關(guān)于一文帶你了解SpringBoot的停機方式的文章就介紹到這了,更多相關(guān)SpringBoot停機方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決springboot jpa @Column columnDefinition等屬性失效問題
這篇文章主要介紹了解決springboot jpa @Column columnDefinition等屬性失效問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
詳解Java構(gòu)建樹結(jié)構(gòu)的公共方法
本文主要介紹了詳解Java構(gòu)建樹結(jié)構(gòu)的公共方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
解決因jdk版本引起的TypeNotPresentExceptionProxy異常
這篇文章介紹了解決因jdk版本引起的TypeNotPresentExceptionProxy異常的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
java 定義長度為0的數(shù)組/空數(shù)組案例
這篇文章主要介紹了java 定義長度為0的數(shù)組/空數(shù)組案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Spring MVC 中攔截器的使用示例詳解"攔截器基本配置"和 &q
Spring MVC 的攔截器作用是在請求到達控制器之前或之后進行攔截,可以對請求和響應(yīng)進行一些特定的處理,這篇文章主要介紹了Spring MVC 中的攔截器的使用“攔截器基本配置” 和 “攔截器高級配置”,需要的朋友可以參考下2024-07-07

