在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

還在使用kill -9 pid結束spring boot項目嗎?

Linux愛好者 ? 來源:CSDN技術社區 ? 作者:流星007 ? 2021-04-13 16:01 ? 次閱讀

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”; }

代碼很簡單,打印:test — start之后讓讓程序休眠100秒,然后再打印:test — end,在線程休眠中我們使用kill -15 pid來結束這個進程,你們猜 test — end會被打印嗎?

application.yml

server: port: 9988

啟動項目

sudo mvn spring-boot:run

這是maven啟動springboot項目的方式

27269916-9b2f-11eb-8b86-12bb97331649.png

看到這個就代表項目啟動成了

找到項目的進程id

sudo ps -ef |grep shutdown

27883e5a-9b2f-11eb-8b86-12bb97331649.png

這個就是項目的進程號,接下來我們先測試test接口,讓線程進入休眠狀態,然后再使用kill -15 14086停止項目

sudo curl 127.0.0.1:9988/test

回到項目日志

27b44838-9b2f-11eb-8b86-12bb97331649.png

我們發現請求已經到達服務,并且線程已經成功進入休眠,現在我們kill -15 14086結束進程

pIYBAGB1UQuActwnAASaBSQr8kc513.png

居然報錯了,但是test — end是打印出來了,為什么會報錯呢?這就和sleep這個方法有關了,在線程休眠期間,當調用線程的interrupt方法的時候會導致sleep拋出異常,這里很明顯就是kill -15 這個命令會讓程序馬上調用線程的interrupt方法,目的是為了讓線程停止,雖然讓線程停止,但線程什么時候停止還是線程自己說的算,這就是為什么我們還能看到:test — end的原因。

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 @Slf4j public 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(); } }

重點在:cyx.close();,為什么他能停止springboot項目呢?請看源碼

public void close() { synchronized(this.startupShutdownMonitor) { this.doClose(); if (this.shutdownHook != null) { try { Runtime.getRuntime().removeShutdownHook(this.shutdownHook); } catch (IllegalStateException var4) { } } } }

程序在啟動的時候向jvm注冊了一個關閉鉤子,我們在執行colse方法的時候會刪除這個關閉鉤子,jvm就會知道這是需要停止服務。

我們看測試結果

282fec72-9b2f-11eb-8b86-12bb97331649.png

28ea8c3a-9b2f-11eb-8b86-12bb97331649.png

很明顯,他也出發了線程的interrupt方法導致線程報錯,原理和kill -15差不多。

actuator

這種方式是通過引入依賴的方式停止服務,actuator提供了很多接口,比如健康檢查,基本信息等等,我們也可以使用他來優雅的停機。

引入依賴

《dependency》 《groupId》org.springframework.boot《/groupId》 《artifactId》spring-boot-starter-actuator《/artifactId》 《/dependency》

application.yml

server: port: 9988 management: endpoints: web: exposure: include: shutdown endpoint: shutdown: enabled: true server: port: 8888

我這里對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”; }

在請求test途中停止服務

28f9bb6a-9b2f-11eb-8b86-12bb97331649.png

我們發現發送停止服務請求之后還給我們返回了提示信息,很人性化,我們看看控制臺

291be906-9b2f-11eb-8b86-12bb97331649.png

292f36aa-9b2f-11eb-8b86-12bb97331649.png

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《ContextClosedEvent》 { private volatile Connector connector; private final int waitTime = 10; @Override public void customize(Connector connector) { this.connector = connector; } @Override public void onApplicationEvent(ContextClosedEvent event) { connector.pause(); Executor executor = connector.getProtocolHandler().getExecutor(); if (executor instanceof ThreadPoolExecutor) { try { ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor; threadPoolExecutor.shutdown(); if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) { System.out.println(“請嘗試暴力關閉”); } } catch (InterruptedException ex) { System.out.println(“異常了”); Thread.currentThread().interrupt(); } } } }

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; @SpringBootApplication public 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; } }

這樣我們就配置好了,我們再來測試一遍,test的接口還是休眠10秒

2961f3c4-9b2f-11eb-8b86-12bb97331649.png

我們發現這次沒有報錯了,他是等待了一段時間之后再結束的線程池,這個時間就是我們在ElegantShutdownConfig類中配置的waitTime。

那可能你會有疑問了,jvm沒有立即停止,那這個時候在有請求會發生什么呢?如果關閉的時候有新的請求,服務將不在接收此請求。

數據備份操作

如果我想在服務停止的時候做點備份操作啥的,應該怎么做呢?其實很簡單在你要執行的方法上添加一個注解即可:@PreDestroy

Destroy:消滅、毀滅

pre:前綴縮寫

所以合在一起的意思就是在容器停止之前執行一次,你可以在這里面做備份操作,也可以做記錄停機時間等。

新增服務停止備份工具類:DataBackupConfig.java

package com.ymy.config; import org.springframework.context.annotation.Configuration; import javax.annotation.PreDestroy; @Configuration public class DataBackupConfig { @PreDestroy public void backData(){ System.out.println(“正在備份數據。。。。。。。。。。。”); } }

我們再來測試然后打印控制臺日志:

29a04a16-9b2f-11eb-8b86-12bb97331649.png

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2967

    瀏覽量

    104751
  • SAM
    SAM
    +關注

    關注

    0

    文章

    112

    瀏覽量

    33522
  • kill
    +關注

    關注

    0

    文章

    9

    瀏覽量

    2105

原文標題:還在使用kill -9 pid結束spring boot項目嗎?不妨試試這幾種優雅的方式!

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    校園點餐訂餐外賣跑腿Java源碼

    創建一個校園點餐訂餐外賣跑腿系統是一個復雜的項目,涉及到前端、后端、數據庫設計等多個方面。在這里,我可以提供一個簡化的Java后端示例,使用Spring Boot框架來搭建一個基本的API服務。這個
    的頭像 發表于 12-24 14:55 ?101次閱讀
    校園點餐訂餐外賣跑腿Java源碼

    SSM開發環境的搭建教程 SSM與Spring Boot的區別

    SSM開發環境的搭建教程 SSM(Spring+SpringMVC+MyBatis)開發環境的搭建涉及多個步驟,以下是詳細的教程: 創建Maven項目 : 使用Maven工具創建一個新的Maven
    的頭像 發表于 12-16 18:13 ?450次閱讀

    Spring 應用合并之路(二):峰回路轉,柳暗花明

    提醒下,決定拋開 Spring Boot 內置的父子容器方案,完全自己實現父子容器。 如何加載 web 項目? 現在的難題只有一個:如何加載 web 項目?加載完成后,如何持續持有 w
    的頭像 發表于 12-12 11:22 ?728次閱讀

    Spring事務實現原理

    作者:京東零售 范錫軍 1、引言 springspring-tx模塊提供了對事務管理支持,使用spring事務可以讓我們從復雜的事務處理中得到解脫,無需要去處理獲得連接、關閉連接、事務提交和回滾等
    的頭像 發表于 11-08 10:10 ?824次閱讀
    <b class='flag-5'>Spring</b>事務實現原理

    android系統使用appe播放audio資源,相關進程被kill之后appe無法再次打開的原因?

    , appe_exit); 來解決程序被kill的時候需要做的資源回收處理,即使用appe_close來釋放資源。 但是,如果使用kill -9結束任務,這個signal是無法被捕
    發表于 10-23 07:56

    Spring Cloud Gateway網關框架

    SpringCloud Gateway功能特征如下: (1) 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 進行構建; (2) 動態路由:能夠匹配任何請求屬性;
    的頭像 發表于 08-22 09:58 ?494次閱讀
    <b class='flag-5'>Spring</b> Cloud Gateway網關框架

    單片機boot0和boot1怎么設置

    單片機Boot0和Boot1簡介 Boot0和Boot1是單片機啟動模式選擇引腳,用于選擇單片機的啟動模式。 Boot0和
    的頭像 發表于 08-22 09:50 ?2543次閱讀

    stm32讀取boot引腳狀態

    在STM32微控制器中,Boot引腳(通常指的是BOOT0和BOOT1引腳)的狀態決定了設備啟動時的引導模式。這些引腳的狀態在復位時被讀取,并據此選擇啟動哪塊存儲器。比如,STM32F103系列
    的頭像 發表于 08-22 09:48 ?1345次閱讀

    stm32boot0和boot1對應哪個p引腳

    STM32系列微控制器是一種廣泛應用于嵌入式系統領域的32位微控制器。在STM32系列微控制器中,BOOT0和BOOT1是兩個重要的引腳,它們用于設置設備的啟動模式。 首先,讓我們了解STM32系列
    的頭像 發表于 08-22 09:40 ?3087次閱讀

    vue+spring boot人員定位系統源碼,實現實時定位、智慧調度、軌跡追蹤

    、機具、物料上定位標簽回傳的位置信息數據,采用多維定位模式,精確定位人、機具、物料的實時位置,實現實時定位、物料標簽配置、智慧調度、軌跡追蹤、工時統計、區域物料統計、電子圍欄等應用功能。 技術架構:java+ spring boot+ v
    的頭像 發表于 08-08 14:27 ?699次閱讀
    vue+<b class='flag-5'>spring</b> <b class='flag-5'>boot</b>人員定位系統源碼,實現實時定位、智慧調度、軌跡追蹤

    玩轉Spring狀態機

    說起Spring狀態機,大家很容易聯想到這個狀態機和設計模式中狀態模式的區別是啥呢?沒錯,Spring狀態機就是狀態模式的一種實現,在介紹Spring狀態機之前,讓我們來看看設計模式中的狀態模式
    的頭像 發表于 06-25 14:21 ?953次閱讀
    玩轉<b class='flag-5'>Spring</b>狀態機

    SpingBoot的5個擴展點,超級實用!

    我們在啟動Spring Boot項目的時候,是執行這樣一個方法來啟動的
    的頭像 發表于 02-22 11:28 ?470次閱讀
    SpingBoot的5個擴展點,超級實用!

    當TPWM模塊kill事件模式為電平觸發時,如何設置電平極性,電平長短,以及Kill事件標記位?

    當TPWM模塊kill事件模式為電平觸發時,如何設置電平極性,電平長短,以及Kill事件標記位
    發表于 02-19 06:52

    Spring事務傳播性的相關知識

    本文主要介紹了Spring事務傳播性的相關知識。
    的頭像 發表于 01-10 09:29 ?447次閱讀
    <b class='flag-5'>Spring</b>事務傳播性的相關知識

    使用Spring Boot 3.2虛擬線程搭建靜態文件服務器

    Spring Boot 3.2 于 2023 年 11 月大張旗鼓地發布,標志著 Java 開發領域的一個關鍵時刻。這一突破性的版本引入了一系列革命性的功能。
    的頭像 發表于 01-09 09:34 ?1126次閱讀
    使用<b class='flag-5'>Spring</b> <b class='flag-5'>Boot</b> 3.2虛擬線程搭建靜態文件服務器
    主站蜘蛛池模板: 久久久精品免费国产四虎| 亚洲国产香蕉视频欧美| 一区二区三区视频| 一级在线观看| 日本网站免费| 三级欧美在线| 狠狠操夜夜| 女人被两根一起进3p在线观看| 欧美性猛交xxxx| 色婷婷九月| 日本免费的一级绿象| 亚洲午夜久久影院| 中文字幕一区在线观看| 日韩免费一级毛片| 天天干天天操天天爽| 欧美深深色噜噜狠狠yyy| 免费黄色大片网站| 在线观看永久免费视频网站| 黄色大片视频网站| 日韩a一级欧美一级| 天天躁狠狠躁| 欧美性猛交xxxx黑人喷水| 天堂在线视频观看| 一级片视频在线观看| 亚洲卡5卡6卡7国色天香| 免费看真人a一级毛片| 狠狠操天天操夜夜操| 香蕉久久久久久狠狠色| 狠狠干奇米| 热九九精品| 性感美女福利视频| 日本高清色视频www| 91大神大战丝袜美女在线观看| 狠狠天天| 色免费在线| 97影院理论| 在线观看视频网站| 性人久久久久| 午夜久久久精品| 亚洲一区二区三区网站| 美女性视频网站|