一、問題
因公司業務的發展,后台架構的變更,導致測試環境(Linux)部署與管理困難成倍增長,duang的一下,增加N倍。進入正題說問題:
問題1. 測試環境包含普通用戶環境、開發者用戶環境,原來只需2個Wildfly,現需要15*2,30個容器,啟動、停止、部署工作量巨大。
1 app
2 appInterface
3 battle
4 friend
5 gexin
6 msg
7 online
8 passport
9 pay
10 push
11 support
12 union
13 upload
14 webInterface
15 webView注:因公司以及其他原因,本文中的模塊名、環境、數量都進行了適當的修改,此處只舉例說明。
問題2. 后續模塊擴展與容器增減維護工作
問題3. 部署包SVN的自動獲取,自動部署問題4. 部署完畢郵件通知
二、分析
1. 現狀
a. SVN源碼無權限,有固定目錄取轉測模塊WAR包,但需要根據轉測svn版本號取(最新的不一定是部署時轉測的模塊)
b. 轉測模塊不定,也許15個,也許2、3個
c. 15個模塊(即15個WAR包),兩環境(普通用戶、開發者用戶),需要30個容器
d. 根據轉測模塊,只需要停止對應模塊所在容器,無須所有模塊停止與啟動
2. 分析與方案確定
1) 棄用Jenkins
a.無須自動構建:公司其他原因,測試無法獲得SVN源碼權限進行自動構建,Jenkins的自動化部署。
b.不夠靈活:WAR的自動化部署,Jenkins雖可部署,但需要15個Job+,整體轉測時用1Job統一部署,如模塊轉測試則需要按每個模塊(每個Job)一一點擊
c.工作量未減少:研發轉測發布固定目錄是以svn版本號發布,在部署時已經可能最新的版本號是另一個轉測模塊,因此需要取對應的版本號,每次改太麻煩,基本沒有減少工作量。
2) 選用Shell腳本
a.腳本實現快速,隨時修改
b.容器的操作都是Linux(shell)命令
c.自動化部署也采用shell分發與檢測部署
d.郵件發送采用mail命令
三、解決問題
1.wildfly統一命名規則
普通用戶環境:Formal-wildfly-模塊名
開發者環境:DEV-wildfly-模塊名
Formal-wildfly-app
Formal-wildfly-appInterface
Formal-wildfly-battle
Formal-wildfly-friend
Formal-wildfly-gexin
...
DEV-wildfly-app
DEV-wildfly-appInterface
DEV-wildfly-battle
DEV-wildfly-friend
DEV-wildfly-gexin
...
2.模塊名稱列表: wildfly.list
app|app
appInterface|ae
battle|b
friend|f
gexin|g
msg|m
online|o
passport|pt
pay|pay
push|ph
support|st
union|un
upload|ud
webInterface|we
webView|ww注意:
a.第一列為模塊名,用於檢測wildfly容器,故需要嚴格注意大小寫
b.第二列為啟動、停止、檢查腳本使用的參數縮寫
c.后續擴展增加模塊,只需要增加對應的容器,然后修改此文件加入模塊名即可,此處解決第2個問題
3.啟動Wildfly腳本(run_wildfly.sh)
# !/bin/bash
# Author:findyou
# Email:1968089885@qq.com
cDate=`date +%Y-%m-%d`
cTime=`date +%H:%M`
shellDIR= " /root/ shell/ "
wildfly_rootDir= " /data/ "
conf_file= " wildfly.list "
echo_tips= " "
checkBoolean=0
# 檢測wildfly.list文件是否存在,不存在-則退出腳本執行
if [ ! -f ${shellDIR}${conf_file} ]; then
echo " Not Found : ${shellDIR}${conf_file} "
exit 1
fi
# 讀wildfly.list文件
count_n=0
while read line;
do
count_n=`expr ${count_n} + 1` # 統計模塊個數
wildfly[$count_n]=`echo $line|cut -d ' | ' -f 1` # 獲到模塊名稱
wildfly_quick[$count_n]=`echo $line|cut -d ' | ' -f 2` # 獲得快捷命令
done < ${shellDIR}${conf_file}
# 腳本幫助提示,並退出腳本
help_tips(){
echo " eg: $0 [wildflyName|a] "
echo ""
echo " wildflyName: "
for ((i=1; i<=${count_n}; i++));
do
echo " ${echo_tips}${wildfly[$i]}|${wildfly_quick[$i]} "
done
echo ""
exit 1
}
# 如果檢測到沒有傳入參數,則執行help_tips方法,
if [ ! -n " $1 " ] ; then
help_tips
fi
# 將傳入的 模塊名稱 參數賦值給para_cmd
para_cmd=$1
# 休眠方法,用於啟動間隔
sleep_2(){
# echo "${echo_tips}${echo_tips}Sleep 2 second!"
sleep 2
}
# 循環啟動Wildfly方法
run_wildfly(){
echo " Time : ${cDate} ${cTime} "
# 循環wildfly.list文件中的所有模塊,根據傳入參數,判斷執行相應的啟動
for ((i=1; i<=${count_n}; i++));
do
# 根據腳本傳入的參數,啟動對應的容器,傳為a則啟動所有容器。
if [ " ${para_cmd} " == " a " -o " ${para_cmd} " == " ${wildfly[$i]} " -o " ${para_cmd} " == " ${wildfly_quick[$i]} " ];then
echo " Start: ${wildfly[$i]} "
# 檢查 普通用戶 對應容器的進程
formal_pc=`ps -ef|grep " Formal-wildfly-${wildfly[$i]}/ "|grep -v grep|wc -l`
# 容器進程數,如果不為0,則說明已啟動。反之則進行容器啟動
if [ $formal_pc -ne 0 ] ; then
echo " ${echo_tips}${echo_tips}Failure: UAT is already running! "
else
echo " ${echo_tips}UAT Start.... "
# 進入對應的容器,啟動容器
cd ${wildfly_rootDir}Formal-wildfly-${wildfly[$i]}/bin
nohup sh standalone.sh >/dev/null 2>&1 &
echo " ${echo_tips}Please Check file: ${wildfly_rootDir}Formal-wildfly-${wildfly[$i]}/standalone/log/server.log "
sleep_2
fi
# 檢查 開發者用戶 對應容器的進程
dev_pc=`ps -ef|grep " Dev-wildfly-${wildfly[$i]}/ "|grep -v grep|wc -l`
if [ $dev_pc -ne 0 ] ; then
echo " ${echo_tips}${echo_tips}Failure: UAT-DEV is already running! "
else
echo " ${echo_tips}UAT-DEV Start.... "
cd ${wildfly_rootDir}Dev-wildfly-${wildfly[$i]}/bin
nohup sh standalone.sh >/dev/null 2>&1 &
echo " ${echo_tips}Please Check file: ${wildfly_rootDir}Dev-wildfly-${wildfly[$i]}/standalone/log/server.log "
sleep_2
fi
# 記錄啟動模塊數
checkBoolean=`expr ${checkBoolean} + 1`
fi
done
}
# 執行run_wildfly方法
run_wildfly
# 傳入了參數,但是沒有找到應的模塊進行啟動,調help_tips
if [ ${checkBoolean} -eq 0 ];then
help_tips
fi說明:
1.wildfly.list須要與run_wildfly.sh放在同一目錄,腳本沒有采用相對路徑,故run_wildfly.sh腳本中需要調整對應的目錄參數shellDIR
2.命令使用,如啟動app容器: ./run_wildfly.sh app
3.啟動所有app容器:./run_wildfly.sh a
4.檢查Wildfly是否運行腳本(check_wildfly.sh)
腳本邏輯與啟動腳本一致,直接替換掉run_wildfly方法即可,但記得調用修改后的方法
check_wildfly(){echo "Time : ${cDate} ${cTime}"
# 循環wildfly.list文件中的所有模塊,根據傳入參數,判斷執行相應的啟動
for ((i=1; i<=${count_n}; i++));
do
# 根據腳本傳入的參數,啟動對應的容器,傳為a則啟動所有容器。
if [ "${para_cmd}" == "a" -o "${para_cmd}" == "${wildfly[$i]}" -o "${para_cmd}" == "${wildfly_quick[$i]}" ];then
echo "Check: ${wildfly[$i]}"
#檢查 普通用戶 對應容器的進程
formal_pc=`ps -ef|grep "Formal-wildfly-${wildfly[$i]}/"|grep -v grep|wc -l`
#容器進程數,如果不為0,則說明已啟動。反之則進行容器啟動
if [ $formal_pc -eq 0 ] ; then
echo "${echo_tips}${echo_tips}UAT not Found!"
else
echo "${echo_tips}UAT is running!"
fi
#檢查 開發者用戶 對應容器的進程
dev_pc=`ps -ef|grep "Dev-wildfly-${wildfly[$i]}/"|grep -v grep|wc -l`
if [ $dev_pc -eq 0 ] ; then
echo "${echo_tips}${echo_tips}UAT-DEV not Found!"
else
echo "${echo_tips}UAT-DEV is running!"
fi
# 記錄啟動模塊數
checkBoolean=`expr ${checkBoolean} + 1`
fi
done
}說明:
1.檢查所有app容器運行狀態:./check_wildfly.sh a
5.停止Wildfly腳本(stop_wildfly.sh)
腳本邏輯與啟動腳本一致,直接替換掉run_wildfly方法即可,但記得調用修改后的方法
stop_wildfly(){
for ((i=1; i<=${count_n}; i++));
do
if [ " ${para_cmd} " == " a " -o " ${para_cmd} " == " ${wildfly[$i]} " -o " ${para_cmd} " == " ${wildfly_quick[$i]} " ];then
echo " Stop: ${wildfly[$i]} "
# 檢查 普通用戶 對應容器的進程,得到進程號
formal_pc=`ps -ef|grep " Formal-wildfly-${wildfly[$i]}/ "|grep -v grep|awk ' {print $2} '`
if [ " $formal_pc " == "" ] ; then
echo " ${echo_tips}${echo_tips}UAT not Found! "
else
# 停止進程
kill -9 $formal_pc
sleep_2
# 再次檢測是否已停止進程
formal_pc1=`ps -ef|grep " Formal-wildfly-${wildfly[$i]}/ "|grep -v grep|awk ' {print $2} '`
if [ " $formal_pc1 " == "" ] ; then
echo " ${echo_tips}Stop UAT Success! "
else
echo " ${echo_tips}${echo_tips}Stop UAT Failure! "
fi
fi
# 檢查 開發者用戶 對應容器的進程,得到進程號
dev_pc=`ps -ef|grep " Dev-wildfly-${wildfly[$i]}/ "|grep -v grep|awk ' {print $2} '`
if [ " $dev_pc " == "" ] ; then
echo " ${echo_tips}${echo_tips}UAT-DEV not Found! "
else
# 停止進程
kill -9 $dev_pc
sleep_2
# 再次檢測是否已停止進程
dev_pc1=`ps -ef|grep " Dev-wildfly-${wildfly[$i]}/ "|grep -v grep|awk ' {print $2} '`
if [ " $dev_pc1 " == "" ] ; then
echo " ${echo_tips}Stop UAT-DEV Success! "
else
echo " ${echo_tips}${echo_tips}Stop UAT-DEV Failure! "
fi
fi
checkBoolean=`expr ${checkBoolean} + 1`
fi
done
}說明:
1.停止所有容器:./stop_wildfly.sh a
至此,第1個問題已圓滿解決!
結束語:
1.原本考慮與實現相對簡單,第一版,把所有的容器路徑寫到文件里,讀取啟動與停止即可,但不利於自動化部署、WAR分發等問題處理。
2.這個版本是實際當中優化的第三個版本,相對擴展與維護簡單,為自動化部署提供停止與啟動腳本,也最適合我們目前的轉測流程。
3.本想與自動部署一起寫此文,發現所講的內容與貼出的腳本內容過多,有時間再講講解決第三、四個問題,超簡單的實現方式shell腳本。
4.Jenkins大多數覺得持續集成用這個很叼,完了其引入除了用發郵件功能、定時任務,其他組件基本用不上。很多人也許只是對Jenkins組件的熟悉,但完全不具備Jenkins轉化提升效率的能力,維護成本與效率還不如之前手工操作。
5.思想的支撐尤為重要,可以在有限的資源里發揮出最大的功效,尋找到最優的方案。
切勿舍本求末,忘記初心!
如轉載還請保留出處與作者姓名Findyou,謝謝!