StringBoot如何進行優(yōu)雅停機

強制停機

無論是Linux的Kill -9 pid還是windows的taskkill /f /pid強制關閉進程,都會帶來一些副作用,如:

  1. 請求丟失:內(nèi)存隊列中等待執(zhí)行的請求丟失;

  2. 數(shù)據(jù)丟失:處于內(nèi)存中的數(shù)據(jù)尚未持久化到磁盤中;

  3. 業(yè)務中斷:處理一半的業(yè)務被強行中斷,卻沒有更新到數(shù)據(jù)庫中;

  4. 文件損壞:正在進行文件的write操作中,突然退出,導致文件損壞;

  5. 鎖表:在操作數(shù)據(jù)庫多表更新時,事務方法執(zhí)行中斷,導致數(shù)據(jù)庫鎖表;

優(yōu)雅停機

Java是通過 JDK 的 ShutdownHook 來完成優(yōu)雅停機的,當程序接收到退出指令后,會標記為退出狀態(tài),此時不再接收新的消息,然后將積壓的消息處理完后回收資源,最后關閉線程。所以不能直接使用kill -9 PID 等強制關閉指令,只有通過 kill -2 PID(Ctrl + C)kill PID (kill -15 PID)時,才會通知程序調(diào)用ShutdownHook方法。通常優(yōu)雅停機需要有等待超時機制,如果在規(guī)定時間內(nèi)還未完成退出前的操作,則由直接調(diào)用kill -9 PID,強制退出。

ShutdownHook用法
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    System.out.println("關閉應用,釋放資源");
}));
優(yōu)雅停機腳本stop.sh
#!/bin/bash

cd `dirname $0`

SERVER_PORT=$1

if [ ! -n "$SERVER_PORT" ]; then
  echo "用法:$0 <SERVER_PORT>"
  exit 1
fi

PIDS=`ps aux | grep java | grep "--server.port=$SERVER_PORT" | awk '{print $2}'`

if [ -z "$PIDS" ]; then
    echo "錯誤: 指定端口的服務進程沒有運行!"
    exit 1
fi

echo -e "正在停止 ...\c"
for PID in $PIDS ; do
    kill $PID > /dev/null 2>&1
done

COUNT=0
NUM=0
#等待程序處理積壓的消息
while [ $COUNT -lt 1 ]; do    
    echo -e ".\c"
    sleep 1
    NUM=$(( $NUM + 1 ))

    COUNT=1
    for PID in $PIDS ; do
        PID_EXIST=`ps -f -p $PID | grep java`
        if [ -n "$PID_EXIST" ]; then
            COUNT=0
            break
        fi
    done

    #90秒超時強制退出
    if [ $NUM -gt 90 ]; then
        for PID in $PIDS ; do
           kill -9 $PID > /dev/null 2>&1
        done
        break
    fi
done

echo "成功關閉進程: $PIDS"

StringBoot配置

spring boot 2.3.x 版本以后,內(nèi)置了優(yōu)雅停機的機制,也就不需要自行擴展容器的線程池來處理, 目前spring boot嵌入式支持的web服務器(Jetty、Reactor Netty、Tomcat 和 Undertow)以及反應式和基于Servlet的web 應用程序都支持優(yōu)雅停機功能。只需在application.yml中添加如下配置即可。

server:
  shutdown: graceful  #關停方式,默認IMMEDIATE(立即關閉)

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s #最大等待線程結(jié)束時間,默認30s

容器表現(xiàn)行為

Web 容器 表現(xiàn)行為
Tomcat 9.0.33+ 停止接收請求,客戶端新請求等待超時。
Reactor Netty 停止接收請求,客戶端新請求等待超時。
Undertow 停止接收請求,客戶端新請求直接返回 503。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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