在linux伺服器上平滑釋出(藍綠髮布)java專案,不影響現有業務執行

wyxazgye發表於2024-07-07

具體操作

  1. 使用nginx作為負載均衡,配置upstream(注意修改專案名)
    upstream 專案名 {
        server localhost:7008 max_fails=3 fail_timeout=30s;
        server localhost:7009 max_fails=3 fail_timeout=30s;
    }
  1. 啟動命令(注意修改jar位置及埠號),後修改為start.sh並開放許可權
#!/bin/sh

RESOURCE_NAME=你的jar具體位置
#預設埠號
DEFAULT_PORT=7008
#另一埠號
ALTERNATE_PORT=7009
STARTUP_TIMEOUT=60  # 等待新服務啟動的超時時間(秒)
CHECK_INTERVAL=2    # 檢查間隔時間(秒)

check_port() {
    netstat -tuln | grep ":$1 " > /dev/null
    return $?
}

start_app() {
    PORT=$1
    nohup java -Xms256m -Xmx512m -jar $RESOURCE_NAME --spring.profiles.active=prod --server.port=$PORT > nohup_$PORT.out 2>&1 &
    echo $! > tpid_$PORT
    echo "應用程式啟動成功,使用埠 $PORT"
}

wait_for_startup() {
    PORT=$1
    TIMEOUT=$2
    INTERVAL=$3
    START_TIME=$(date +%s)
    
    while [ $(($(date +%s) - $START_TIME)) -lt $TIMEOUT ]; do
        check_port $PORT
        if [ $? -eq 0 ]; then
            echo "埠 $PORT 的應用程式已啟動"
            return 0
        fi
        echo "等待埠 $PORT 的應用程式啟動..."
        sleep $INTERVAL
    done
    
    echo "等待超時,埠 $PORT 的應用程式未啟動"
    return 1
}

stop_app() {
    PORT=$1
    tpid=$(ps -ef | grep $RESOURCE_NAME | grep $PORT | grep -v grep | grep -v kill | awk '{print $2}')
    if [ -n "$tpid" ]; then
        echo "停止程序,埠 $PORT, PID: $tpid..."
        kill -15 $tpid
        sleep 5
        tpid=$(ps -ef | grep $RESOURCE_NAME | grep $PORT | grep -v grep | grep -v kill | awk '{print $2}')
        if [ -n "$tpid" ]; then
            echo "強制終止程序,PID: $tpid..."
            kill -9 $tpid
        else
            echo "程序停止成功!"
        fi
    else
        echo "未找到埠 $PORT 的程序停止。"
    fi
}

# 檢查預設埠是否被佔用
check_port $DEFAULT_PORT
if [ $? -eq 0 ]; then
    echo "埠 $DEFAULT_PORT 已被佔用,使用埠 $ALTERNATE_PORT 啟動應用程式"
    start_app $ALTERNATE_PORT
    
    if wait_for_startup $ALTERNATE_PORT $STARTUP_TIMEOUT $CHECK_INTERVAL; then
        echo "停止使用埠 $DEFAULT_PORT 的應用程式"
        stop_app $DEFAULT_PORT
    else
        echo "備用埠的應用程式啟動失敗,保持原服務執行"
    fi
else
    echo "埠 $DEFAULT_PORT 未被佔用,使用該埠啟動應用程式"
    start_app $DEFAULT_PORT
    
    if wait_for_startup $DEFAULT_PORT $STARTUP_TIMEOUT $CHECK_INTERVAL; then
        echo "停止使用埠 $ALTERNATE_PORT 的應用程式"
        stop_app $ALTERNATE_PORT
    else
        echo "預設埠的應用程式啟動失敗,保持備用服務執行"
    fi
fi

echo "服務切換完成!"

說明:

啟動應用程式:start_app 函式啟動應用程式,並指定使用的埠。
等待應用程式完全啟動:
wait_for_startup 函式會在指定的超時時間內輪詢檢查指定埠是否已經開始監聽(應用程式是否已完全啟動)。
這個函式會每 CHECK_INTERVAL 秒檢查一次埠,直到超過 STARTUP_TIMEOUT 秒。
停止舊的應用程式:只有在新的應用程式完全啟動後,才會停止舊的應用程式。
超時處理:如果在指定時間內新服務未能啟動,將會輸出相應的資訊,並保留原服務繼續執行。
使用說明:
STARTUP_TIMEOUT:等待新服務啟動的最大時間(秒)。
CHECK_INTERVAL:檢查新服務是否啟動的間隔時間(秒)。

相關文章