賴正華
(中移信息技術有限公司,廣東 深圳 518048)
現在很多的業務系統引用微服務化的思想,將業務系統的功能在應用程序實現上進行解耦處理:每個功能由單獨的程序模塊來提供,再將各個程序模塊,利用消息隊列的形式串聯起來。假如應用程序分為了前置程序、業務處理程序。前置程序接受請求后,通過MQ消息中間件將消息通過點對點的方式分發到業務處理程序。業務處理程序根據不同的請求渠道以及用戶歸屬省等因素,可將消息引流到不同的業務處理程序去消費消息,比如對業務量很大的省份或者渠道,由A主機單獨提供服務,對業務量小的省份或者渠道可以多個省或渠道共享一臺主機消費消息,利用MQ的點對點消息,實現了流量的分流。因此,在代碼打包編譯時,需要對不同的業務處理節點標識不同的appcode,每一個tomcat運行單獨標識appcode的業務處理war包程序,這樣便可實現點對點消息消費。由于承載的是全網的業務,部署的服務器數量和tomcat容器數量會達到數十個,且隨著業務規模的發展,服務器的數量一直在增長,因此在每次進行變更上線時,運維人員的工作強度和壓力越來越大。且系統屬于實時交易類系統,為在全球漫游的用戶提供無間斷的服務,對系統變更上線提出了高要求:需要不間斷提供服務且快速又準確地完成變更上線操作。本文將對這種業務場景的系統上線方式展開研究。
目前行業內用于自動化上線的開源工具有Ansible、Saltstack、Jenkins等。
Ansible是一種基于Paramiko開發的自動化運維工具。通過SSH協議與遠程主機相結合,并以模塊化的方式實現批量部署、自動化執行命令等功能。基于Ansible可以實現批量的操作,比如對批量的tomcat進行停啟操作,對批量的tomcat下的webapp目錄替換相同的war包程序,但Ansible不適合這種業務場景:系統涉及有數十個tomcat節點,每個節點運行的war包程序不同,因此Ansible工具無法實現對這數十個運行不同war程序的tomcat進行批量的操作。
Saltstack也是類似的情況,只能對相同的命令執行批量操作,不適合這種不同主機的操作命令不同、變更上線的程序版本不同且涉及的主機數量眾多的業務場景。
Jenkins是一款開源CI&CD軟件,用于自動化各種任務,包括構建、測試和部署軟件[1]。本文基于Jenkins的Publish Over SSH插件實現將上線程序從Jenkins服務器分發到應用主機,并執行shell腳本實現變更上線的流水線操作:應用程序備份、停tomcat進程、刪原來的程序文件、移新版本程序文件到指定目錄、更改配置文件、啟動tomcat進程、檢查進程是否啟動等操作。
本文將基于Jenkins設計一種方案,可實現實時交易系統的不中斷上線。首先,若需要實現業務系統的不中斷上線,需要對業務系統的部署進行重新設計,原來的業務系統由前置程序寫消息到消息隊列中,業務處理節點從MQ服務器監聽并拉取消息處理,而且是采用點對點的消息隊列模式,如果未采用主備的模式部署,那么在變更上線時,需要重啟tomcat操作,消息沒有消費者來消費,此時會導致業務中斷。現在改為部署主備式的業務處理,打包編譯時,對war包加上標簽appcodeA和appcodeB,兩個業務處理節點都監控消息隊列A,都可以從這個隊列拉取消息處理,兩個tomcat都可以監聽這個消息隊列A,實行搶消息的方式去消費消息。其他的業務處理節點也做類似的部署調整,這樣業務系統在MQ的作用下,實現了分布式的部署,且每個業務處理、前置程序都具備了主備節點,如圖1所示。這樣在日常的變更操作時,如果對主節點進行重啟操作的時候,消息隊列A的消息可以被備tomcat節點進行消費,正常提供對外訪問,實現業務不中斷。但隨之帶來的是tomcat數量的翻倍。

圖1 業務應用分布式化部署
在對應用系統進行了部署優化后,在Jenkins管理界面,添加遠程主機;然后對每一個tomcat配置一個job任務,在job任務的配置界面編寫遠程執行的shell命令。按照上線操作的流水操作編寫shell命令。當觸發這個任務時,能單獨完成這個tomcat節點的進程啟停、文件備份與換新等操作。
在對所有的主節點配置完成job任務后,將所有的主節點job加入到一個新的job中,如圖2所示。

圖2 主備節點job列表
同理對所有的備節點,每個節點配置一個job任務,在job任務中配置對應的shell命令,實現各個節點可以個性化地操作tomcat。將所有的備節點job加入到新的一個job中,任命為BUSI-BACK,如圖2所示。這樣便可以將所有的主節點歸納到一個job,所有的備節點歸納到另一個job,可實現并發操作。
在上線變更操作時,依次對主節點的控制任務BUSIMAIN觸發工程構建操作,如圖3所示,此時所有主節點的tomcat會并發的進行上線操作,極大地縮短上線變更時間。此時,備節點的tomcat從消息隊列讀取消息進行消息處理,對外表現為業務未中斷。在主節點完成上線變更操作后,再對備節點進行工程構建操作,此時主節點的所有tomcat從消息隊列拉取消息進行業務處理,對外表現也是業務不中斷。

圖3 主備節點的控制job列表
首先在部署主機運行Jenkins服務:nohup java-jar jenkins.war--httpPort=8080&。在瀏覽器輸入Jenkins的訪問界面:http://localhost:8080,按照提示輸入密鑰后即可進入Jenkins服務的管理界面[2]。
Jenkins具有可伸縮的插件機制,集成人員可以很方便地進行配置的自主性選擇,根據自己所需要的插件進行安裝、刪除和添加。進入到首界面的系統管理界面后,再進入到插件管理界面,本文的方案需要安裝Publish Over SSH插件包,在生產環境需要采用離線安裝的方式[3]。
接下來是新建job的工作,即如圖2所示的BN-S-001即為一個獨立的job。在界面中進行配置和shell命令編寫工作。在配置界面中,需要配置目標主機的信息,即job的名稱,需要配置上線文件的source files的正則表達式,在本文中配置為*,即匹配任何的文件,本文中默認所有的主節點命名為BN-S-00*,備節點則命名為BN-S-10*。在本文中將實現對一個tomcat進行如下流水線式的操作:備份原webapps目錄下的程序文件、kill tomcat進程、休眠一段時間待tomcat完成上一筆業務、再次kill tomcat進程、刪除原webapps目錄下的所有war包程序和war包解壓后的程序文件、刪除配置文件、將要上線的新程序war包文件拷貝到webapps目錄下、拷貝新的配置文件到配置目錄下、啟動tomcat進程。每一個tomcat都需要進行類似的流水操作。
實現的shell腳本如下:

在每個job中都完成上述的job配置,以及把shell命令拷貝到每個job的command窗口中便可完成配置[4]。配置完成后的效果如圖2所示。
將所有的BN-S-00*開頭的job作為主節點編排在BUSIMAIN這個job中,將BN-S-10*開頭的job編排到BUSIBACK這個job中作為備節點。對BUSI-MAIN這個job點擊構建操作,即可觸發這個job下的所有主節點job進行并發的構建,所有的job并發的執行shell命令,完成流水線式的操作。在對BUSI-MAIN這個job完成構建的時刻,tomcat是不提供對外服務的,此時作為備節點的BN-S-10*節點均正常對外提供服務。在BUSI-MAIN這個job完成構建后,即完成了新版本上線后,再對BUSI-BACK這個job進行相同的操作,此時主節點對外提供服務,如圖4所示。經過實測,單人對55個tomcat進行正常的變更上線操作,需要花費的時間在2個小時以上,但利用本文的方案實現,可在5分鐘內完成上線工作,不中斷業務系統的服務,且可大大降低人為錯誤操作的風險。

圖4 測試結果
本文針對實時交易業務系統在進行不中斷業務變更上線提出了一種解決方案。適用的業務場景為每個tomcat或者其他容器所承載的應用程序版本不同,但又需要批量上線的情況。利用Jenkins可定制化地實現每個tomcat或容器實現不同的流水線操作,最終進行搭積木式的組合調用。本文結合業務系統的部署情況,對部署進行了優化改進,以實現變更上線過程不中斷業務的功能[5]。經過實測,該方案能極大提高上線的效率和準確度。