kill -9 關閉程式
kill -9 pid ???
kill可將指定的資訊送至程式。預設的資訊為SIGTERM(15),可將指定程式終止。若仍無法終止該程式,可使用SIGKILL(9)資訊嘗試強制刪除程式。程式或工作的編號可利用ps指令或jobs指令檢視(這段話來自菜鳥教程)。
講的這個複雜,簡單點來說就是用來殺死linux中的程序,啥?你問我啥是程序?請自行百度。
我相信很多人都用過kill -9 pid 這個命令,徹底殺死程序的意思,一般情況我們使用它沒有上面問題,但是在我們專案中使用它就有可能存在致命的問題。
kill -9 pid 帶來的問題
由於kill -9 屬於暴力刪除,所以會給程式帶來比較嚴重的後果,那究竟會帶來什麼後果呢?
舉個例子:轉賬功能,再給兩個賬戶進行加錢扣錢的時候突然斷電了?這個時候會發生什麼事情?對於InnoDB儲存引擎來說,沒有什麼損失,因為它支援事務,但是對於MyISAM引擎來說那簡直就是災難,為什麼?假如給A賬戶扣了錢,現在需要將B賬戶加錢,這個時候停電了,就會造成,A的錢被扣了,但是B沒有拿到這筆錢,這在生產環境是絕對不允許的,kill -9 相當於突然斷電的效果。
當然了,像轉賬這種,肯定不是使用MyISAM引擎,但是如今分散式火了起來,跨服務轉賬已經是很平常的事情,這種時候如果使用kill -9 去停止服務,那就不是你的事務能保證資料的準確性了,這個時候你可能會想到分散式事務,這個世界上沒有絕對的安全系統或者架構,分散式事務也是一樣,他也會存在問題,機率很小,如果一旦發生,損失有可能是無法彌補的,所以一定不能使用kill -9 去停止服務,因為你不知道他會造成什麼後果。
在MyISAM引擎中表現得更明顯,比如使用者的資訊由兩張表維護,管理員修改使用者資訊的時候需要修改兩張表,但由於你的kill -9 暴力結束專案,導致只修改成功了一張表,這也會導致資料的不一致性,這是小事,因為大不了再修改一次,但是金錢、合同這些重要的資訊如果由於你的暴力刪除導致錯亂,我覺得可能比刪庫跑路還嚴重,至少刪庫還能恢復,你這個都不知道錯在哪裡。
那我們應該怎麼結束專案呢?
其實java給我們提供了結束專案的功能,比如:tomcat可以使用shutdown。bat/shutdown。sh進行優雅結束。
什麼叫優雅結束?
“第一步:停止接收請求和內部執行緒。第二步:判斷是否有執行緒正在執行。第三步:等待正在執行的執行緒執行完畢。第四步:停止容器。”
以上四步才是正常的結束流程,那springboot怎麼正常結束服務呢?下面我介紹幾種正常結束服務的方案,請拿好小本本做好筆記。
優雅結束服務
kill -15 pid
這種方式也會比較優雅的結束程序(專案),使用他的時候需要慎重,為什麼呢?我們來看個例子
我寫了一個普通的controller方法做測試
@GetMapping(value = “/test”) public String test(){ log。info(“test ——- start”); try { Thread。sleep(100000); } catch (InterruptedException e) { e。printStackTrace(); } log。info(“test ——- end”); return “test”; }1234567891011
程式碼很簡單,列印:test — start之後讓讓程式休眠100秒,然後再列印:test — end,線上程休眠中我們使用kill -15 pid來結束這個程序,你們猜 test — end會被列印嗎?
application.yml
server: port: 998812
啟動專案
sudo mvn spring-boot:run1
這是maven啟動springboot專案的方式
看到這個就代表專案啟動成了
找到專案的程序id
sudo ps -ef |grep shutdown1
這個就是專案的程序號,接下來我們先測試test介面,讓執行緒進入休眠狀態,然後再使用kill -15 14086停止專案
sudo curl 127。0。0。1:9988/test1
回到專案日誌
我們發現請求已經到達服務,並且執行緒已經成功進入休眠,現在我們kill -15 14086結束程序
sudo kill -15 140861
回到日誌
2020-04-24 10:53:14。939 INFO 14086 ——- [nio-9988-exec-1] com。ymy。controller。TestController : test ——- start2020-04-24 10:54:02。450 INFO 14086 ——- [extShutdownHook] o。s。s。concurrent。ThreadPoolTaskExecutor : Shutting down ExecutorService ‘applicationTaskExecutor’java。lang。InterruptedException: sleep interrupted at java。lang。Thread。sleep(Native Method) at com。ymy。controller。TestController。test(TestController。java:26) at sun。reflect。NativeMethodAccessorImpl。invoke0(Native Method) at sun。reflect。NativeMethodAccessorImpl。invoke(NativeMethodAccessorImpl。java:62) at sun。reflect。DelegatingMethodAccessorImpl。invoke(DelegatingMethodAccessorImpl。java:43) at java。lang。reflect。Method。invoke(Method。java:498) at org。springframework。web。method。support。InvocableHandlerMethod。doInvoke(InvocableHandlerMethod。java:190) at org。springframework。web。method。support。InvocableHandlerMethod。invokeForRequest(InvocableHandlerMethod。java:138) at org。springframework。web。servlet。mvc。method。annotation。ServletInvocableHandlerMethod。invokeAndHandle(ServletInvocableHandlerMethod。java:105) at org。springframework。web。servlet。mvc。method。annotation。RequestMappingHandlerAdapter。invokeHandlerMethod(RequestMappingHandlerAdapter。java:879) at org。springframework。web。servlet。mvc。method。annotation。RequestMappingHandlerAdapter。handleInternal(RequestMappingHandlerAdapter。java:793) at org。springframework。web。servlet。mvc。method。AbstractHandlerMethodAdapter。handle(AbstractHandlerMethodAdapter。java:87) at org。springframework。web。servlet。DispatcherServlet。doDispatch(DispatcherServlet。java:1040) at org。springframework。web。servlet。DispatcherServlet。doService(DispatcherServlet。java:943) at org。springframework。web。servlet。FrameworkServlet。processRequest(FrameworkServlet。java:1006) at org。springframework。web。servlet。FrameworkServlet。doGet(FrameworkServlet。java:898) at javax。servlet。http。HttpServlet。service(HttpServlet。java:634) at org。springframework。web。servlet。FrameworkServlet。service(FrameworkServlet。java:883) at javax。servlet。http。HttpServlet。service(HttpServlet。java:741) at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:231) at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) at org。apache。tomcat。websocket。server。WsFilter。doFilter(WsFilter。java:53) at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) at org。springframework。web。filter。RequestContextFilter。doFilterInternal(RequestContextFilter。java:100) at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) at org。springframework。web。filter。FormContentFilter。doFilterInternal(FormContentFilter。java:93) at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) at org。springframework。boot。actuate。metrics。web。servlet。WebMvcMetricsFilter。doFilterInternal(WebMvcMetricsFilter。java:109) at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) at org。springframework。web。filter。CharacterEncodingFilter。doFilterInternal(CharacterEncodingFilter。java:201) at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) at org。apache。catalina。core。StandardWrapperValve。invoke(StandardWrapperValve。java:202) at org。apache。catalina。core。StandardContextValve。invoke(StandardContextValve。java:96) at org。apache。catalina。authenticator。AuthenticatorBase。invoke(AuthenticatorBase。java:541) at org。apache。catalina。core。StandardHostValve。invoke(StandardHostValve。java:139) at org。apache。catalina。valves。ErrorReportValve。invoke(ErrorReportValve。java:92) at org。apache。catalina。core。StandardEngineValve。invoke(StandardEngineValve。java:74) at org。apache。catalina。connector。CoyoteAdapter。service(CoyoteAdapter。java:343) at org。apache。coyote。http11。Http11Processor。service(Http11Processor。java:373) at org。apache。coyote。AbstractProcessorLight。process(AbstractProcessorLight。java:65) at org。apache。coyote。AbstractProtocol$ConnectionHandler。process(AbstractProtocol。java:868) at org。apache。tomcat。util。net。NioEndpoint$SocketProcessor。doRun(NioEndpoint。java:1594) at org。apache。tomcat。util。net。SocketProcessorBase。run(SocketProcessorBase。java:49) at java。util。concurrent。ThreadPoolExecutor。runWorker(ThreadPoolExecutor。java:1149) at java。util。concurrent。ThreadPoolExecutor$Worker。run(ThreadPoolExecutor。java:624) at org。apache。tomcat。util。threads。TaskThread$WrappingRunnable。run(TaskThread。java:61) at java。lang。Thread。run(Thread。java:748)2020-04-24 10:54:04。574 INFO 14086 ——- [nio-9988-exec-1] com。ymy。controller。TestController : test ——- end2020-04-24 10:54:04。610 ERROR 14086 ——- [nio-9988-exec-1] o。s。web。servlet。HandlerExecutionChain : HandlerInterceptor。afterCompletion threw exceptionjava。lang。NullPointerException: null at org。springframework。boot。actuate。metrics。web。servlet。LongTaskTimingHandlerInterceptor。stopLongTaskTimers(LongTaskTimingHandlerInterceptor。java:123) ~[spring-boot-actuator-2。2。6。RELEASE。jar:2。2。6。RELEASE] at org。springframework。boot。actuate。metrics。web。servlet。LongTaskTimingHandlerInterceptor。afterCompletion(LongTaskTimingHandlerInterceptor。java:79) ~[spring-boot-actuator-2。2。6。RELEASE。jar:2。2。6。RELEASE] at org。springframework。web。servlet。HandlerExecutionChain。triggerAfterCompletion(HandlerExecutionChain。java:179) ~[spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。servlet。DispatcherServlet。triggerAfterCompletion(DispatcherServlet。java:1427) [spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。servlet。DispatcherServlet。doDispatch(DispatcherServlet。java:1060) [spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。servlet。DispatcherServlet。doService(DispatcherServlet。java:943) [spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。servlet。FrameworkServlet。processRequest(FrameworkServlet。java:1006) [spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。servlet。FrameworkServlet。doGet(FrameworkServlet。java:898) [spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at javax。servlet。http。HttpServlet。service(HttpServlet。java:634) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。springframework。web。servlet。FrameworkServlet。service(FrameworkServlet。java:883) [spring-webmvc-5。2。5。RELEASE。jar:5。2。5。RELEASE] at javax。servlet。http。HttpServlet。service(HttpServlet。java:741) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:231) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。tomcat。websocket。server。WsFilter。doFilter(WsFilter。java:53) [tomcat-embed-websocket-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。springframework。web。filter。RequestContextFilter。doFilterInternal(RequestContextFilter。java:100) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。springframework。web。filter。FormContentFilter。doFilterInternal(FormContentFilter。java:93) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。springframework。boot。actuate。metrics。web。servlet。WebMvcMetricsFilter。doFilterInternal(WebMvcMetricsFilter。java:109) [spring-boot-actuator-2。2。6。RELEASE。jar:2。2。6。RELEASE] at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。springframework。web。filter。CharacterEncodingFilter。doFilterInternal(CharacterEncodingFilter。java:201) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。springframework。web。filter。OncePerRequestFilter。doFilter(OncePerRequestFilter。java:119) [spring-web-5。2。5。RELEASE。jar:5。2。5。RELEASE] at org。apache。catalina。core。ApplicationFilterChain。internalDoFilter(ApplicationFilterChain。java:193) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。ApplicationFilterChain。doFilter(ApplicationFilterChain。java:166) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。StandardWrapperValve。invoke(StandardWrapperValve。java:202) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。StandardContextValve。invoke(StandardContextValve。java:96) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。authenticator。AuthenticatorBase。invoke(AuthenticatorBase。java:541) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。StandardHostValve。invoke(StandardHostValve。java:139) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。valves。ErrorReportValve。invoke(ErrorReportValve。java:92) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。core。StandardEngineValve。invoke(StandardEngineValve。java:74) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。catalina。connector。CoyoteAdapter。service(CoyoteAdapter。java:343) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。coyote。http11。Http11Processor。service(Http11Processor。java:373) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。coyote。AbstractProcessorLight。process(AbstractProcessorLight。java:65) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。coyote。AbstractProtocol$ConnectionHandler。process(AbstractProtocol。java:868) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。tomcat。util。net。NioEndpoint$SocketProcessor。doRun(NioEndpoint。java:1594) [tomcat-embed-core-9。0。33。jar:9。0。33] at org。apache。tomcat。util。net。SocketProcessorBase。run(SocketProcessorBase。java:49) [tomcat-embed-core-9。0。33。jar:9。0。33] at java。util。concurrent。ThreadPoolExecutor。runWorker(ThreadPoolExecutor。java:1149) [na:1。8。0_242] at java。util。concurrent。ThreadPoolExecutor$Worker。run(ThreadPoolExecutor。java:624) [na:1。8。0_242] at org。apache。tomcat。util。threads。TaskThread$WrappingRunnable。run(TaskThread。java:61) [tomcat-embed-core-9。0。33。jar:9。0。33] at java。lang。Thread。run(Thread。java:748) [na:1。8。0_242]123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
居然報錯了,但是test — end是打印出來了,為什麼會報錯呢?這就和sleep這個方法有關了,線上程休眠期間,當呼叫執行緒的interrupt方法的時候會導致sleep丟擲異常,這裡很明顯就是kill -15 這個命令會讓程式馬上呼叫執行緒的interrupt方法,目的是為了讓執行緒停止,雖然讓執行緒停止,但執行緒什麼時候停止還是執行緒自己說的算,這就是為什麼我們還能看到:test — end的原因。更多的 Spring Boot 影片教程可以關注微信訂閱號碼將筆記回覆 Spring Boot 獲取。
ConfigurableApplicationContext colse
我們先看怎麼實現
package com。ymy。controller;import lombok。extern。slf4j。Slf4j;import org。springframework。beans。BeansException;import org。springframework。context。ApplicationContext;import org。springframework。context。ApplicationContextAware;import org。springframework。context。ConfigurableApplicationContext;import org。springframework。web。bind。annotation。GetMapping;import org。springframework。web。bind。annotation。PostMapping;import org。springframework。web。bind。annotation。RestController;@RestController@Slf4jpublic class TestController implements ApplicationContextAware { private ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this。context = applicationContext; } @GetMapping(value = “/test”) public String test(){ log。info(“test ——- start”); try { Thread。sleep(100000); } catch (InterruptedException e) { e。printStackTrace(); } log。info(“test ——- end”); return “test”; } /** * 停機 */ @PostMapping(value = “shutdown”) public void shutdown(){ ConfigurableApplicationContext cyx = (ConfigurableApplicationContext) context; cyx。close(); }}1234567891011121314151617181920212223242526272829303132333435363738394041424344
重點在:cyx。close();,為什麼他能停止springboot專案呢?請看原始碼
public void close() { synchronized(this。startupShutdownMonitor) { this。doClose(); if (this。shutdownHook != null) { try { Runtime。getRuntime()。removeShutdownHook(this。shutdownHook); } catch (IllegalStateException var4) { } } } }123456789101112
程式在啟動的時候向jvm註冊了一個關閉鉤子,我們在執行colse方法的時候會刪除這個關閉鉤子,jvm就會知道這是需要停止服務。
我們看測試結果
很明顯,他也觸發了執行緒的interrupt方法導致執行緒報錯,原理和kill -15差不多。
actuator
這種方式是透過引入依賴的方式停止服務,actuator提供了很多介面,比如健康檢查,基本資訊等等,我們也可以使用他來優雅的停機。
引入依賴
application.yml
server: port: 9988management: endpoints: web: exposure: include: shutdown endpoint: shutdown: enabled: true server: port: 888812345678910111213
我這裡對actuator的介面重新給定了一個介面,這樣可提高安全性,下面我們來測試一下
@RequestMapping(value = “/test”,method = RequestMethod。GET) public String test(){ System。out。println(“test ——- start”); try { Thread。sleep(10000); } catch (InterruptedException e) { e。printStackTrace(); } System。out。println(“test ——- end”); return “hello”; }1234567891011
在請求test途中停止服務
我們發現傳送停止服務請求之後還給我們返回了提示資訊,很人性化,我們看看控制檯
test — end被執行了,不過在停止執行緒池的時候還是呼叫了執行緒的interrupt方法,導致sleep報錯,這三種方式都可以比較優雅的停止springboot服務,如果我專案中存線上程休眠,我希望10秒以後再停止服務可以嗎?肯定是可以的,我們只需要稍微做點修改就可以了。
1.新增停止springboot服務類:ElegantShutdownConfig.java
package com。ymy。config;import org。apache。catalina。connector。Connector;import org。springframework。boot。web。embedded。tomcat。TomcatConnectorCustomizer;import org。springframework。context。ApplicationListener;import org。springframework。context。event。ContextClosedEvent;import java。util。concurrent。Executor;import java。util。concurrent。ThreadPoolExecutor;import java。util。concurrent。TimeUnit;public class ElegantShutdownConfig implements TomcatConnectorCustomizer, ApplicationListener
2.在啟動類中加入bean
package com。ymy;import com。ymy。config。ElegantShutdownConfig;import lombok。extern。slf4j。Slf4j;import org。apache。catalina。connector。Connector;import org。springframework。boot。SpringApplication;import org。springframework。boot。autoconfigure。SpringBootApplication;import org。springframework。boot。web。embedded。tomcat。TomcatConnectorCustomizer;import org。springframework。boot。web。embedded。tomcat。TomcatServletWebServerFactory;import org。springframework。boot。web。servlet。server。ServletWebServerFactory;import org。springframework。context。ApplicationListener;import org。springframework。context。ConfigurableApplicationContext;import org。springframework。context。annotation。Bean;import org。springframework。context。event。ContextClosedEvent;import java。util。concurrent。Executor;import java。util。concurrent。ThreadPoolExecutor;import java。util。concurrent。TimeUnit;@SpringBootApplicationpublic class ShutdownServerApplication { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication。run(ShutdownServerApplication。class, args); run。registerShutdownHook(); } @Bean public ElegantShutdownConfig elegantShutdownConfig() { return new ElegantShutdownConfig(); } @Bean public ServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat。addConnectorCustomizers(elegantShutdownConfig()); return tomcat; }}1234567891011121314151617181920212223242526272829303132333435363738394041
這樣我們就配置好了,我們再來測試一遍,test的介面還是休眠10秒
我們發現這次沒有報錯了,他是等待了一段時間之後再結束的執行緒池,這個時間就是我們在ElegantShutdownConfig類中配置的waitTime。
那可能你會有疑問了,jvm沒有立即停止,那這個時候在有請求會發生什麼呢?如果關閉的時候有新的請求,服務將不再接收此請求。
資料備份操作
如果我想在服務停止的時候做點備份操作啥的,應該怎麼做呢?其實很簡單在你要執行的方法上新增一個註解即可:@PreDestroy
“Destroy:消滅、毀滅 pre:字首縮寫”
所以合在一起的意思就是在容器停止之前執行一次,你可以在這裡面做備份操作,也可以做記錄停機時間等。
新增服務停止備份工具類:DataBackupConfig。java
package com。ymy。config;import org。springframework。context。annotation。Configuration;import javax。annotation。PreDestroy;@Configurationpublic class DataBackupConfig { @PreDestroy public void backData(){ System。out。println(“正在備份資料……。。。。。”); }}123456789101112131415
我們再來測試然後列印控制檯日誌: