1.關(guān)于主機(jī)部署
1.1. 趨勢
部署環(huán)境一直在演變,從物理機(jī)油挥,虛擬機(jī)潦蝇,到容器化平臺(tái),這個(gè)趨勢是明顯的深寥,是不可否認(rèn)的攘乒,這個(gè)我們不做過多討論,
本文所提的方案是在需要主機(jī)(物理機(jī)惋鹅、虛擬機(jī))部署的前提下進(jìn)行的则酝。
1.2.優(yōu)點(diǎn)
- 簡單,沒有過多的依賴與封裝,簡單意味著可靠
- 故障定位快沽讹,部署環(huán)境越復(fù)雜般卑,因環(huán)境引起的故障定位越困難,當(dāng)然此話有點(diǎn)絕對(duì)爽雄,但統(tǒng)計(jì)學(xué)上看蝠检,是這樣的
1.3.缺點(diǎn)
資源限制欠缺
比如限制CPU占用,內(nèi)存占用挚瘟,雖然java有內(nèi)存限制的方法叹谁,但此方法只適用java,其他開發(fā)語言的項(xiàng)目乘盖,可能也有焰檩,但限制方式不統(tǒng)一,同時(shí)很多語言沒有限制的方法控制能力不足
比如動(dòng)態(tài)縮容订框,擴(kuò)容析苫,這些高級(jí)特性,需要自己寫服務(wù)去實(shí)現(xiàn)穿扳,容器化平臺(tái)很多是帶這個(gè)功能
2. 部署設(shè)計(jì)
2.1.運(yùn)維分工
-
運(yùn)維人員
- 數(shù)據(jù)庫衩侥、緩存、存儲(chǔ)纵揍、操作系統(tǒng)等基礎(chǔ)中間件
- 系統(tǒng)監(jiān)控
- 告警處理進(jìn)度的跟蹤及匯總
- 服務(wù)簡單的起停操作顿乒,日志查看
-
開發(fā)人員(自己負(fù)責(zé)的服務(wù))
- 服務(wù)的上線
- 服務(wù)線上告警及故障的處理
2.2.用戶隔離
- 不同項(xiàng)目有共用機(jī)器(這個(gè)不常見)
- 同一個(gè)項(xiàng)目议街,不同環(huán)境有共用機(jī)器(比如預(yù)發(fā)布環(huán)境與生產(chǎn)環(huán)境有部分主機(jī)重疊)
- 同一個(gè)項(xiàng)目泽谨,中間件和業(yè)務(wù)服務(wù)共用機(jī)器
#以開放平臺(tái)項(xiàng)目為例(osp),應(yīng)用運(yùn)行在普通用戶
useradd osp && echo Osp_2018 | passwd --stdin osp
2.3.目錄設(shè)計(jì)
- 為了用戶隔離特漩,應(yīng)用部署目錄放在用戶目錄下
- 為了避免JRE的相互干擾吧雹,在~/apps/java目錄存放自己的Server JRE(比如server-jre-8u172-linux-x64.tar.gz解壓縮到j(luò)ava目錄),并在app_env.conf明確指定JAVA_EXE涂身,這樣大家升級(jí)jdk相互不干擾
/home/osp/apps
- apps
應(yīng)用部署根目錄- java
JRE目錄 - {app_code}
具體的應(yīng)用目錄- {server_port}
應(yīng)用端口號(hào)雄卷,以支持單機(jī)部署多個(gè)實(shí)例- app_env.conf
應(yīng)用啟動(dòng)腳本參數(shù)文件 - run.sh
應(yīng)用啟動(dòng)腳本 - logs
應(yīng)用日志目錄,日志文件一定要限制大小,比如springboot 默認(rèn)的一個(gè)文件10M,最多存7個(gè)文件 - {app_code}-{app_version}.jar
應(yīng)用部署包
- app_env.conf
- {server_port}
- java
2.4 應(yīng)用啟動(dòng)腳本
腳本已經(jīng)開源蛤售,歡迎大家完善這個(gè)腳本丁鹉,開源項(xiàng)目地址:https://github.com/Hanson1330/spring-boot-run
2.4.1. boot.conf
#java程序路徑(必需)
JAVA_EXE=~/apps/java/jdk1.8.0_181/bin/java
#注冊(cè)中心地址(如果未啟用注冊(cè)中心,可注釋)
#DISCOVERY_URI="http://user:password@127.0.0.1:8761/eureka/"
#配置文件選擇
PROFILES_ACTIVE=dev
#服務(wù)端口(必需)
SERVER_PORT=8080
#JVM配置(必需)
JVM_ARGS="-server -Xms256m -Xmx1024m -Djava.io.tmpdir=/var/tmp -Duser.timezone=Asia/Shanghai"
#命令行參數(shù)
CMD_LINE_ARGS=""
2.4.2 run.sh
#!/bin/bash
# -------------------------------------------------------------------------------
# version: 2.0
# Date: 2018-08-25 10:00
# Author: Ma Yonglong
# Email: yonglong.ma@hpe.com
# Description: Spring Boot應(yīng)用運(yùn)行腳本悴能,支持Mac,Linux
# -------------------------------------------------------------------------------
#應(yīng)用主目錄
cd "$(dirname "$0")" || exit 1
APP_HOME=$(pwd)
LOG_DIR="${APP_HOME}/logs"
PID_FILE="${APP_HOME}/app.pid"
BOOT_CONF="${APP_HOME}/boot.conf"
#應(yīng)用JAR
APP_JAR="$(find "${APP_HOME}" -name "*.jar" 2>/dev/null | head -n 1)"
#應(yīng)用名稱
APP_NAME=${APP_JAR##*/}
APP_NAME=${APP_NAME%.jar}
#操作
ACTION=$1
echoRed() { echo $'\e[0;31m'"$1"$'\e[0m'; }
echoGreen() { echo $'\e[0;32m'"$1"$'\e[0m'; }
echoYellow() { echo $'\e[0;33m'"$1"$'\e[0m'; }
usage() {
echo $'\n\n\n'
echoRed "Usage: ${0} support command {start|stop|restart|status|cleanup}"
echo $'\n\n\n'
exit 1
}
psCheck() {
echo "--------------All instances on this machine--------------"
echo "USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND" && echo ""
ps aux | grep "$APP_NAME" | grep -E -v "grep"
}
#根據(jù)PID_FILE檢查是否在運(yùn)行
isRunning() {
[[ -f "$PID_FILE" ]] || return 1
ps -p "$(<"$PID_FILE")" &>/dev/null
}
#1.檢查操作參數(shù)
[ $# -gt 0 ] || usage
#2.引入啟動(dòng)配置
if [ -r "$BOOT_CONF" ]; then
. "$BOOT_CONF"
else
echoRed "Missing or unreadable $BOOT_CONF"
echo $'\n\n\n'
exit 1
fi
#基礎(chǔ)配置
BASE_ARGS="--spring.profiles.active=$PROFILES_ACTIVE --server.port=$SERVER_PORT"
if [ ! "$DISCOVERY_URI" = "" ]; then
BASE_ARGS="$BASE_ARGS --eureka.client.serviceUrl.defaultZone=$DISCOVERY_URI"
fi
RUN_EXE="$JAVA_EXE $JVM_ARGS -jar $APP_JAR $BASE_ARGS $CMD_LINE_ARGS"
start() {
echo "--------------Starting $APP_NAME:"
echo $'\n\n\n'
#檢查jdk
if [ -z "$JAVA_EXE" ]; then
echoRed "Result: Start failed,Cannot find a Java JDK. Please check JAVA_EXE in boot.conf"
echo $'\n\n\n'
exit 1
fi
#檢查已經(jīng)運(yùn)行
if (isRunning); then
echoYellow "Result: Running, no need to start"
echo $'\n\n\n'
exit 0
fi
#打印啟動(dòng)命令
echo "-------Boot Command: "
echo "nohup $RUN_EXE >/dev/null 2>${LOG_DIR}/error.log &"
echo $'\n\n\n'
#創(chuàng)建錯(cuò)誤日志文件
mkdir -p "$LOG_DIR" && touch "${LOG_DIR}/error.log"
#啟動(dòng)
nohup $RUN_EXE >/dev/null 2>>"${LOG_DIR}/error.log" &
#記錄pid到pid文件
echo $! >"$PID_FILE"
#命令執(zhí)行異常揣钦,快速失敗
sleep 0.5
if (! isRunning); then
echoRed "Result: Start failed" && rm -f "$PID_FILE"
echo $'\n\n\n'
exit 1
fi
#啟動(dòng)幾秒鐘中后失敗的情況,6秒內(nèi)失敗
sleep 6
if (! isRunning); then
echoRed "Result: Start failed" && rm -f "$PID_FILE"
echo $'\n\n\n'
exit 1
fi
#啟動(dòng)幾秒鐘中后失敗的情況漠酿,10秒內(nèi)失敗
sleep 4
if (! isRunning); then
echoRed "Result: Start failed" && rm -f "$PID_FILE"
echo $'\n\n\n'
exit 1
fi
#啟動(dòng)幾秒鐘中后失敗的情況冯凹,啟動(dòng)在10秒外失敗的比例比較低,而且也不可能一直等炒嘲,這種情況交給監(jiān)控告警來解決
echoGreen "Result: Start success,Running (PID: $(<"$PID_FILE"))"
echo $'\n\n\n'
#檢查本機(jī)存在的實(shí)例
psCheck
}
stop() {
echo "--------------Stopping $APP_NAME:"
echo $'\n\n\n'
if (! isRunning); then
echoYellow "Result: Not running" && rm -f "$PID_FILE"
echo $'\n\n\n'
return 0
fi
kill "$(<"$PID_FILE")" 2>/dev/null
#30秒后強(qiáng)制退出
TIMEOUT=30
while isRunning; do
if ((TIMEOUT-- == 0)); then
kill -KILL "$(<"$PID_FILE")" 2>/dev/null
fi
sleep 1
done
rm -f "$PID_FILE"
echoGreen "Result: Stop success"
echo $'\n\n\n'
}
status() {
echo "--------------Status $APP_NAME:"
echo $'\n\n\n'
if isRunning; then
echoGreen "Result: Running (PID: $(<"$PID_FILE"))"
else
echoYellow "Result: Not running"
fi
echo $'\n\n\n'
psCheck
}
cleanup() {
echo "--------------Cleanup $APP_NAME:"
echo $'\n\n\n'
if ! isRunning; then
[[ -d "$LOG_DIR" ]] || {
echoGreen "Result: Log does not exist, there is no need to clean up" && echo $'\n\n\n'
return 0
}
rm -rf "$LOG_DIR"
echoGreen "Result: Log cleared"
else
echoYellow "Result: Please stop the application first and then clean up the log"
fi
echo $'\n\n\n'
}
case "$ACTION" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
cleanup)
cleanup
;;
*)
usage
;;
esac
#成功退出
exit 0