Java代碼自動部署 【 ①Java代碼自動部署-總結簡介】 代碼部署是每一個軟體開發項目組都會有的一個流程,也是從開發環節到發佈功能必不可少的環節。對於Java開發者來說,Java代碼的發佈部署也是經常需要做的一件事,特別是互聯網公司。代碼的發佈上線關係到保證生產環境能夠正常啟動及功能是否能正常運 ...
Java代碼自動部署
【 ①Java代碼自動部署-總結簡介】
代碼部署是每一個軟體開發項目組都會有的一個流程,也是從開發環節到發佈功能必不可少的環節。對於Java開發者來說,Java代碼的發佈部署也是經常需要做的一件事,特別是互聯網公司。代碼的發佈上線關係到保證生產環境能夠正常啟動及功能是否能正常運行,所以代碼部署在整個項目開發周期還是占據很重要的地位。
由於本人近期在學習Java代碼自動發佈相關的知識,此系列文章是對此次學習到的知識進行鞏固和總結;同時,也希望能夠幫助到和我一樣對此方面知識感興趣的同行們。言不多說,直接進入真題。下麵針對此次系列文章做一個簡要的概述。
1、學習代碼自動部署的目的
高效且簡化代碼的部署發佈
2、使用的相關工具及技術
1、 CentOS操作系統(可以使用虛擬機安裝Linux系統)
2、 Maven
3、 Git
4、 Shell腳本
5、 Jenkins
3、學習代碼自動發佈相關技術的順序
階段1:
優點:部署流程簡單方面,開發完成後開發人員在開發環境即可進行代碼部署上線。
缺點:發佈流程粗糙,代碼部署不夠嚴謹,不建議生產環境使用此方式。
階段2:
優點:由Git進行項目版本管理,降低了代碼發佈的風險,發佈過程有運維人員進行發佈。
缺點:由於代碼的發佈由運維人員發佈,需開發人員配合進行代碼發佈部署,與發佈部署不成功,得由開發人員查找問題,增加了部署複雜性。
階段3:
優點:由Jenkins工具進行代碼的發佈部署,規範了代碼的發佈流程,提供可視工具監聽整個發佈流程等。
缺點:對技術要求更高了,需要瞭解Jenkins工具,會編寫Shell腳本等。
4、Java代碼自動部署總結分為以下系列
①總結簡介
②使用Maven進行代碼部署
③使用Shell進行代碼部署
④使用Jenkins進行代碼部署
⑤課程總結及心得
【 ②使用Maven進行代碼部署】
在使用maven進行代碼發佈的時候,需要用Maven工具的相關插件將需要部署的項目發佈到指定的伺服器的部署目錄中。
在學習此技術時,我用的的是一個秒殺項目的ssm版,大家在學學習此技術的時候可以用簡單一點的Maven項目進行測試。因本項目是學習如何進行部署項目技術的,本次就針對具體項目進行介紹。
1、 使用Maven進行部署項目要求
1) 項目本身屬於Maven項目(必要條件)
2) 需要部署的是war包
3) 引入插件
在需要部署的項目的pom,xml文件中引入tomcat插件,在project->build-> plugins節點引入tomcat插件。
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <!-- 引入tomcat插件 --> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <!-- <url>http://localhost:8080/manager</url> --> <!-- tomcat6部署管理路徑 --> <url>http://192.168.25.133:8080/manager/text</url> <!-- tomcat7部署管理路徑 --> <!-- tomcat控制台賬號 --> <username>admin</username> <!-- tomcat的管理員賬號 --> <!-- tomcat控制台密碼--> <password>admin</password> <!-- 本地運行時指定的埠號 --> <port>8080</port> <path>/seckill-manager</path> <!-- 部署路徑 --> <charset>UTF-8</charset> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> |
4) 執行Maven的redeploy操作
執行的命令:tomcat7:redeploy
在eclipse下配置的命令如下:
2、需要註意的問題點
1、在將項目發佈到遠程Tomcat時需要啟動遠程Tomcat管理控制台賬號
開啟tomcat管理控制台賬號地址為:Tomcat安裝目錄/conf/tomcat-users.xml文件
在tomcat-users.xml文件中需要配置允許訪問純文本介面許可權,以便maven的tomat插件能夠通過此方式進行部署項目。
在tomcat-users節點新增role屬性和user屬性,如下:
<role rolename="manager-script" /> <role rolename="manager-gui"/> <user username="admin" password="admin" roles="manager-gui,manager-script"/> |
解釋:給賬號admin配置manager-script及manager-gui許可權
Tomcat角色解釋圖:
2、在需要遠程發佈到的目標Tomcat應該是運行狀態,保證Maven的tomcat插件能夠訪問到目標Tomcat完成項目的部署。
【③使用Shell進行代碼部署】
在使用Shell腳本進行重新部署項目時,需要掌握Shell腳本的編寫,Shell腳本需要完成以下功能:
1、 將代碼clone到伺服器指定目錄
2、 根據pom.xml文件將代碼打包成war包
3、 將war發佈到指定伺服器
環境要求:
1、 安裝Maven並配置環境變數
2、 Git客戶端,並配置環境變數
3、 熟悉Shell腳本相關知識
1、編寫Shell腳本
在Linux的指定目錄新建shell腳本,我是在項目的專用tomcat根目錄新建了shell腳本,方便進行tomcat集群部署操作。腳本內容如下:
#!/bin/bash #shell功能概要:seckill的service提供者構建shell #發佈service提供者的伺服器的進程名 serverName="seckill_provider" #獲取發佈service提供者的伺服器的進程PID PID=$(ps -ef | grep $serverName | grep -v grep | awk '{ print $2 }') #java代碼本地倉庫地址 javaBaseSrc="/opt/java_project_src/" #項目路徑 javaProjectSrc="sekill/seckill-manager/seckill-service/target/seckill-service.war" #發佈的tomcat集群,數組方式存儲 projectServicersPath=(/opt/seckill-tomcat/seckill-tomcat-02 /opt/seckill-tomcat/seckill-tomcat-03) projectName="sekill" #迴圈強制停止指定tomcat for var in ${PID}; do echo "準備強制停止PID:$var" kill -9 $var done echo "kill $serverName sucess" #切換到git本地倉庫目錄 cd $javaBaseSrc #刪除倉庫庫中代碼 rm -rf $projectName echo "從/opt/java_project_src倉庫中刪除項目$projectName成功" #從遠程倉庫下載代碼,因涉及到賬戶信息,此處更改為描述信息 git clone 遠程git倉庫項目URL cd $javaBaseSrc/sekill/seckill-manager #安裝項目並跳過測試 mvn -Dmaven.test.skip=true clean install #判斷執行上面mvn操作的返回值是否為0 if [ $? -ne 0 ] then echo "構建失敗,請查看代碼問題!" exit 1; fi #迴圈將項目部署到集群tomcat中 for projectServicer in ${projectServicersPath[@]} do cp $javaBaseSrc$javaProjectSrc $projectServicer/webapps echo "$projectServicer 代碼發佈成功!" sh $projectServicer/bin/startup.sh if [ $? -ne 0 ] then echo "$projectServicer 啟動失敗" exit 1; else echo "$projectServicer 啟動成功"; fi done echo "啟動 $serverName 成功" |
2、需要註意的問題點
在編寫Shell腳本時需要知道每句Shell的含義,儘可能將所有問題點都能考慮到,比如:
a) 強殺進程問題
進行PID=$(ps -ef | grep $serverName | grep -v grep | awk '{ print $2 }')時,要確定查詢的只是目標Tomcat的進程pid,防止在後續強制停止時將其他應用Tomcat誤強行停止,這裡建 議給每一個目標Tomcat設置指定的進程名,設置方法為:
在指定tomcat的bin/ setclasspath.sh文件中找到if [ -z "$_RUNJAVA" ]判斷語句,進行以下設置即可
if [ -z "$_RUNJAVA" ]; then #_RUNJAVA="$JRE_HOME"/bin/java cp "$JAVA_HOME/bin/java" "$JAVA_HOME/bin/seckill_consumer01" _RUNJAVA="$JRE_HOME/bin/seckill_consumer01" fi |
b) Shell腳本儘可能通用
我吸取了現在比較流行的一句話“約定大於配置”及平時所看所想,在編寫Shell腳本時可以提取可變或多處使用的變數,使整個Shell腳本儘可能提煉成通用,以便類似項目部署可以使用現有腳本進行更改後使用,減少重新編寫新Shell腳本帶來不可控的問題。
【④使用Jenkins進行代碼部署】
在使用Jenkins進行項目部署時,需要將Jenkins的war包放在伺服器的指定位置。Jenkins的war的下載可以去Jenkins的官網進行下載。
使用Jenkins進行代碼部署時需要的環境支持:
1、安裝Maven並配置環境變數
2、Git客戶端,並配置環境變數
3、熟悉Shell腳本相關知識
4、對Jenkins有一定瞭解
使用Jenkins進行代碼部署如下:
1、 啟動Jenkins工具
在jenkins.war目錄執行以下命令操作啟動Jenkins工具。
[xiongshx@localhost jenkins]$ java -jar jenkins.war
Jenkins工具初始化的一些操作可以百度或者去Jenkins查看可以參考【https://www.cnblogs.com/cheng95/p/6542036.html】
初始化後需要進行的配置
工具配置
【系統管理】->【全局工具配置】
Jdk配置:
Git配置:
Maven配置:
2、 新建任務
需要註意的點:
1、填寫源碼倉庫地址
2、構建時操作及自定義shell代碼
Shell代碼如下:
#!/bin/bash #shell功能概要:seckill的Web消費者構建shell #引用的技術有:git、maven #發佈web消費者的伺服器的進程名 serverName="seckill_consumer" #獲取發佈web消費者的伺服器的進程PID PID=$(ps -ef | grep $serverName | grep -v grep | awk '{ print $2 }') #需要在腳本開始時添加export BUILD_ID=dontKillMe。 #原因:因為Jenkins執行完當前任務之後需要執行下一個任務,此時Jenkins會直接把tomcat進程殺掉, #因此在腳本中編寫的tomcat啟動命令是不會執行的。 export BUILD_ID=dontKillMe #java代碼本地倉庫地址 javaBaseSrc="/home/xiongshx/.jenkins/workspace/" #項目路徑 javaProjectSrc="seckill/seckill-web/target/seckill-web.war" #發佈的tomcat projectServicersPath=(/opt/seckill-tomcat/seckill-tomcat-01) projectName="sekill" for var in ${PID}; do echo "準備強制停止PID:$var" kill -9 $var done echo "kill $serverName sucess" #如果上一個命令執行失敗,執行的狀態碼不為0 if [ $? -ne 0 ] then echo "構建失敗,請查看代碼問題!" exit 1; fi for projectServicer in ${projectServicersPath[@]} do cp $javaBaseSrc$javaProjectSrc $projectServicer/webapps echo "$projectServicer 代碼發佈成功!" /bin/bash $projectServicer/bin/startup.sh if [ $? -ne 0 ] then echo "$projectServicer 啟動失敗" exit 1; else echo "$projectServicer 啟動成功"; fi done echo "啟動 $serverName 成功" |
3、 啟動項目
【立即構建】->【點擊構建的鏈接】->【控制台輸出】即可查看整個代碼部署過程中的信息輸出。
4、需要註意的問題點:
1、Jenkins的war問題
最簡單jenkins.war的啟動方式是在控制台終端執行命令:java -jar jenkins.war;但是此方法會占用一個終端視窗,且關閉後Jenkins工具就不能進行訪問,可以使用命令進行後臺執行,命令如下:
nohup java -jar jenkins.war --httpPort=9090 > /dev/null 2>&1 &
命令解釋:
nohup 後臺執行操作
--httpPort=9090表示指定占用9090埠進行訪問
> /dev/null 將日誌輸出到/dev/null
2>&1 & 用來將標準錯誤2重定向到標準輸出1中的此處1前面的&就是為了讓bash將1解釋成標準輸出而不是文件1。最後一個&,則是讓bash在後臺執行。
另外一種更優雅的方式是使用Shell腳本控制Jenkins工具的啟動、停止、重啟等操作。
樣例如下:
#!/bin/bash #功能描述:用於Jenkins運行,停止,重啟 #將此腳本放在jenkins.war同級目錄
#獲取Jenkins的進程id pid=$(ps -ef| grep "jenkins.war" | grep -v grep | awk '{print $2}') #jenkins預設埠號 jekinsDefaultPort=9090 #如果用戶有自定義埠號,則使用用戶自定義的埠號啟動jenkins if [ x$2 != x ] then jekinsDefaultPort=$2 fi
#啟動jenkins start(){ if [ x$pid != x ] then echo "jenkins已經是啟動狀態..." exit 1 fi nohup java -jar jenkins.war --httpPort=$jekinsDefaultPort > /dev/null 2>&1 & echo "jenkins啟動成功,埠號為:$jekinsDefaultPort..." return $? }
stop(){ echo "準備停止jenkins..." if [ x$pid != x ] then kill -9 $pid echo "jenkins已經停止..." exit $? else echo "jenkins的進程id不存在,無法進行停止操作..." exit 1 fi }
# 重新載入Jenkins restart() { stop start echo "jenkins重新載入成功,jekins埠號為:$jekinsDefaultPort..." }
case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo $"提示: 請在jenkins後輸入以下參數:{start|stop|restart} 埠號(不填寫時預設埠9090)" exit 1 esac exit $? |
2、Jenkins中自定義Shell問題
#需要在腳本開始時添加export BUILD_ID=dontKillMe。
#原因:因為Jenkins執行完當前任務之後需要執行下一個任務,此時Jenkins會直接把tomcat進程殺掉,#因此在腳本中編寫的tomcat啟動命令是不會執行的。
export BUILD_ID=dontKillMe
【⑤課程總結及心得】
學習代碼自動部署的緣由一來是由於在平時開發過程中經常會遇到代碼部署的環節,希望通過學習此知識後,如果後續有機會針對自己學會的方案進行評估後簡化項目中的項目部署,二來是鞏固自己近期來學習到的一些知識,通過層層迭進來學習代碼的自動部署方案。雖然目前自己的這些流程方案可能還有所欠缺,且還沒有經過實際項目考驗,但能學到很多實際的知識也足夠了,比如Maven相關知識、Shell相關知識以及Jenkins相關知識,這些是只能通過自己動手慢慢去實踐才能獲取到的經驗。如果對代碼部署也感興趣且覺得我寫的東西對你有幫助的同行們,我建議可以按照我的學習步驟去學習自動構建技術。
此系列文章可能寫的還不夠好,並且很多地方我都進行了一些精簡。其實我希望給大家提供的是一個思路。比如學習整個項目部署的思路,由Maven插件部署到Shell腳本部署再到Jenkins部署項目,其實越到後面,Jenkins只是對一些操作做了集成封裝,但是我覺得如果我們能從最基本做起,瞭解其中的流程及原理,真正使用Jenkins進行代碼部署時,我們能知道所以然,那樣我覺得可以更好的使用Jenkins工具。另外,比如Jenkins.war的啟動,我很自然的想到使用Shell腳本將它的啟動、運行、重啟等命令進行封裝,並把它設置為開機啟動,我覺得這是一個優雅的方式,以後有類似的情況時,我也會考慮這麼做。
本文中還有一些沒有提及和沒有實現的內容,我希望以及對此技術感興趣的同行們,都可以發散思維,把事情盡善盡美,做到最優做好。通過編寫此系列文章,我鞏固了我此類技術的知識的瞭解以及拓展,也希望能夠幫助到大家。如果大家在學習此類技術上遇到疑惑或問題,可以百度查看解決辦法,也可以給我留言進行探討。
最後,希望所有人在不久的將來都能遇到一個優秀的自己。