請不要在用kill -9這種粗魯?shù)姆绞浇Y(jié)束jvm

樓主目前就職于某互聯(lián)網(wǎng)公司,也在傳統(tǒng)金融公司呆過,看過身邊很多同事發(fā)布的時(shí)候都是直接kill -9 pid,場面一度十分粗魯,然而這樣會(huì)有什么問題嗎?這樣在項(xiàng)目啟動(dòng)的時(shí)候沒有注冊hook,會(huì)導(dǎo)致在項(xiàng)目重新發(fā)布的時(shí)候,如果已經(jīng)正在處理請求會(huì)被強(qiáng)制關(guān)閉,甚至導(dǎo)致異常,而且還沒有做補(bǔ)償機(jī)制.

背景:目前我們的服務(wù)都是集群的,發(fā)布的時(shí)候會(huì)一臺臺切過去,假如當(dāng)前有三個(gè)節(jié)點(diǎn),節(jié)點(diǎn)正準(zhǔn)備發(fā)布了,首先腳本了會(huì)執(zhí)行調(diào)用stop命令去關(guān)閉當(dāng)前服務(wù)的進(jìn)程,這個(gè)時(shí)候首先服務(wù)應(yīng)該踢出集群,如果有新請求進(jìn)來,負(fù)載策略會(huì)把當(dāng)前新的請求打到節(jié)點(diǎn)二或者節(jié)點(diǎn)三上面,節(jié)點(diǎn)一不在接收新的請求了,繼續(xù)處理殘余的請求,對結(jié)束現(xiàn)場進(jìn)行清理,已保證現(xiàn)場.

慎用kill -9 pid(如果能保證當(dāng)前不會(huì)有請求進(jìn)來),或者當(dāng)前服務(wù)是一個(gè)批量任務(wù),那么可以忽略.

啟動(dòng)腳本init.script里面kill pid默認(rèn)是kill -15 pid,這個(gè)才是真正的去關(guān)閉進(jìn)程,當(dāng)用kill pid的時(shí)候,首先會(huì)發(fā)出interrupt的中斷指令,之前注冊過的hook監(jiān)聽到指令,線程池本身不在接收新的請求了,這個(gè)時(shí)候可以釋放線程池的資源,等當(dāng)前所以的線程都結(jié)束以后,才平滑的退出,這樣就可以保證服務(wù)不間斷,24小時(shí)不停服務(wù).

目前一下這些操作都會(huì)觸發(fā)shutdownhook

1)程序正常退出

2)使用System.exit()

3)終端使用Ctrl+C觸發(fā)的中斷

4)系統(tǒng)關(guān)閉

5)OutOfMemory宕機(jī)

6)使用Kill pid命令干掉進(jìn)程(注:在使用kill -9 pid時(shí),是不會(huì)被調(diào)用的)


Demo:

下面以線程池為例:

package com.example.hook;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.concurrent.*;

import static java.lang.Thread.sleep;

@SpringBootApplication

public class HookApplication {

static ThreadPoolExecutorthreadPool =new ThreadPoolExecutor(2, 6, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(10), new RejectedExecutionHandler() {

@Override

public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

System.out.println("reject ------");

}

});

public static void main(String[] args) {

SpringApplication.run(HookApplication.class, args);

Runtime.getRuntime().addShutdownHook(new Thread(() -> test2()));

for(int i=1;i<=10;i++){

threadPool.submit(() ->test1(1));

}

}

public static void test1(int i) {

try {

sleep(3000);

}catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("當(dāng)前打印的數(shù)字是: " + i);

}

public static void test2() {

threadPool.shutdown();

while (!threadPool.isTerminated()) {

try {

System.out.println("還有線程沒有關(guān)閉");

TimeUnit.SECONDS.sleep(5);

}catch (InterruptedException e) {

e.printStackTrace();

}

}

System.out.println("shut down!");

}

}

測試結(jié)果:

kill -9 57283

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

程序被強(qiáng)制結(jié)束了

kill 57542

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

還有線程沒有關(guān)閉

當(dāng)前打印的數(shù)字是: 1

當(dāng)前打印的數(shù)字是: 1

shut down!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 服務(wù)如何優(yōu)雅的退出 樓主目前就職于某互聯(lián)網(wǎng)公司,也在傳統(tǒng)金融公司呆過,看過身邊很多同事發(fā)布的時(shí)候都是直接kill ...
    他是人間惆悵客閱讀 2,752評論 0 27
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 5,182評論 1 114
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,594評論 1 15
  • 沒錯(cuò),你沒看錯(cuò)題目。 你可能瞬間就啟動(dòng)了大腦的搜索模式,尋找?guī)讉€(gè)有力的論據(jù)來反駁我了吧? 那行,我我先敲幾個(gè)問題放...
    拆那小哥哥閱讀 641評論 3 6
  • 圣誕節(jié)快樂,今天每個(gè)小朋友都很開心的來幼兒園,帶著圣誕老人送的禮物,辰辰?jīng)]有什么表情,他不相信有圣誕老人。希望相信...
    徐小豆呀閱讀 264評論 0 0

友情鏈接更多精彩內(nèi)容