以前,咱們公司部署以及升級都是由運維去管理的,聯想到不少開源平臺都支持自動升級,索性我也作個自動升級war的功能。
這裏沒有用docker鏡像發包,灰度發包等,只適用於單個tomcat的部署環境,支持docker單個tomcat容器。java
先簡單分析下war包自動升級流程:linux
1,2步驟中沒有什麼坑,主要是3,4,5步驟,若是用java代碼去執行,當tomcat服務關閉時,war包內的代碼將中止,因此除非單獨寫個java程序跑才能繼續執行下面代碼。但又以爲這種方式麻煩,對環境依賴過高,最終採用shell腳本去執行3,4,5步驟,而java-web去調用這個shell腳本便可。web
這一步比較簡單,這裏直接發送一個請求,帶上版本號,如:
a.com/checkVersio…
返回是否須要更新,以及更新地址:sql
{
"NeedUpdate": true,
"downUrl": "http://a.com/1.0.war"
}複製代碼
這裏使用httpclient去調用接口:docker
/*使用時注意字符集 "GBK""UTF-8"*/
public static String visitPost(String urlStr, String code) {
try{
URL url = new URL(urlStr);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestMethod("GET");
con.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(),code));));
String line;
StringBuffer buffer = new StringBuffer();
while((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
con.disconnect();
String res = buffer.toString();
return res;
} catch(Exception e) {
e.printStackTrace();
}
return null;
}複製代碼
相似方法有不少種,這裏不舉例。下載以後使用fastjson或者gson或者純string解析出內容便可。shell
java的下載文件方法有不少種,都是以流的形式寫,代碼量比較多,若是項目裏有框架的話,直接用就能夠了,沒有的話,網上找一個。json
/**
* 保存附件
* 一、保存附件信息到附件表
* 二、保存文件到相應的目錄
*
* @param file 文件實體
*/
public boolean saveFile(FileEntity file) {
BufferedOutputStream bos = null;
FileOutputStream fos = null;
byte[] bytes = file.getBytes();
if (bytes != null) {
try {
fos = new FileOutputStream(file_Path + file.getName());
bos = new BufferedOutputStream(fos);
bos.write(bytes);
bos.flush();
IOUtils.closeQuietly(fos);
IOUtils.closeQuietly(bos);
return true;
} catch (Exception e) {
IOUtils.closeQuietly(fos);
IOUtils.closeQuietly(bos);
Log.error("保存文件失敗", e);
return false;
}
}
return false;
}複製代碼
runBatOrShell(packagename, System.getProperties().getProperty("os.name").indexOf("Windows") != -1)複製代碼
這裏須要判斷Windows仍是linux,true爲Windows,不然爲linux。引入包名參數是爲了獲得sh文件及bat文件。tomcat
private String tomcat_Path = System.getProperty("catalina.base") + File.separator;//服務器路徑
/**
* 執行方法腳本
* @param 路徑
* @param 系統
*/
public boolean runBatOrShell( String name, boolean os) {
Log.info("runBatOrShell start:>>>>>>>>>>>>>>>>>>>>");
String _path;
try {
_path = os ? this.getClass().getResource("/batshell/web.bat").getPath() + " " + file_Path + " "+ name + " " + tomcat_Path : "sh " + this.getClass().getResource("/batshell/web.sh").getPath() + " " + file_Path + " "+ name + " " + tomcat_Path;
Log.info(_path);
Process ps = Runtime.getRuntime().exec(_path);
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream(), "UTF-8"));//注意中文編碼問題
String line;
while ((line = br.readLine()) != null) {
Log.info("runBatOrShell info=========>" + line);
}
br.close();
} catch (IOException ioe) {
Log.error("runBatOrShell error !!!!!!!!!!");
ioe.printStackTrace();
return false;
}
return true;
}複製代碼
這裏引入tomcat路徑是爲了方便腳本執行。
sh web.sh空格
war文件目錄空格
文件名空格
tomcat目錄
sh web.sh /usr/local/war/ 1.0.war /usr/local/tomcat/
bat文件同理
web.bat d:/war/ 1.0.war d:/tomcat/
文件目錄以下:
bash
#!/bin/sh
cd $1
echo $(date +%Y-%m-%d-%l:%M:%S) >>webvlog.txt;
echo $2>>webvlog.txt;
echo "正在關閉tomcat">>webvlog.txt;
sh $3/bin/shutdown.sh
echo "正在執行刪除war.war">>webvlog.txt;
rm $3/webapps/war.war;
echo "正在執行刪除war文件夾">>webvlog.txt;
rm -r $3/webapps/war;
echo "正在部署war">>webvlog.txt;
cp $1$2 $3/webapps/war.war
echo "正在重啓tomcat">>webvlog.txt;
sh $3/bin/startup.sh
echo "部署成功">>webvlog.txt;複製代碼
其中$1 $2 $3 這種變量標示運行時後面的傳值,其它代碼echo就是註釋。webvlog.txt爲部署日誌。服務器
這樣改造後,基本知足目前現有需求,也簡化了部署步驟。但沒法適用多tomcat環境中,不少場景有load balance負載均衡、有多個docker環境,此時,該方案便沒法解決。
war包在升級時,可能會增長表、視圖等,因此還須要執行sql腳本,sql腳本升級方案下次分享。