苗 凡,閻志遠(yuǎn),戴琳琳
(中國(guó)鐵道科學(xué)研究院集團(tuán)有限公司 電子計(jì)算技術(shù)研究所,北京 100081)
客票系統(tǒng)核心交易中間件線上包括CTMS、INETIS、CTMSX等,主要為鐵路12306網(wǎng)站、12306 APP提供接口服務(wù)。線下包括CTMS、AFCIS、TVMIS等,主要為窗口、代售點(diǎn)、自動(dòng)售票機(jī)、閘機(jī)等提供接口服務(wù)。其中,CTMSX、INETIS與CTMS部署在鐵路總公司的兩個(gè)數(shù)據(jù)中心,共同承擔(dān)各渠道的交易請(qǐng)求??推毕到y(tǒng)日均售票800萬(wàn)張,節(jié)假日高峰期超過(guò)1 200萬(wàn)張[1],中間件服務(wù)作為交易系統(tǒng)中的重要一環(huán),在保證系統(tǒng)的穩(wěn)定性中起著重要的作用。
交易中間件的應(yīng)用均含有多個(gè)配置文件,根據(jù)業(yè)務(wù)場(chǎng)景的不同,替換的配置文件也不同。當(dāng)前中間件服務(wù)更換配置文件后,需要重啟服務(wù)才能生效,若服務(wù)與其它應(yīng)用保持長(zhǎng)連接,還需要通知其它應(yīng)用進(jìn)行重連,整個(gè)升級(jí)可能需要10 min才能恢復(fù),極大地影響了生產(chǎn)環(huán)境的可用性[2]。為解決上述問(wèn)題,本文提出了一種基于Zookeeper進(jìn)行配置管理的方案,Zookeeper是一個(gè)高可用的分布式數(shù)據(jù)管理與系統(tǒng)協(xié)調(diào)框架,能夠保證分布式環(huán)境中數(shù)據(jù)的一致性。
Zookeeper 采用了類似文件系統(tǒng)目錄樹(shù)型結(jié)構(gòu)的數(shù)據(jù)模型,結(jié)構(gòu)中的每一個(gè)節(jié)點(diǎn)稱為znode。與文件系統(tǒng)不同的是,每個(gè)節(jié)點(diǎn)具有與之對(duì)應(yīng)的數(shù)據(jù)內(nèi)容,可以擴(kuò)展任意的節(jié)點(diǎn)和葉子節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都可以存儲(chǔ)KB級(jí)別的數(shù)據(jù)[3]。節(jié)點(diǎn)維護(hù)一個(gè)stat數(shù)據(jù)結(jié)構(gòu)(包括數(shù)據(jù)變化的版本號(hào)、ACL變化、時(shí)間戳),以允許緩存驗(yàn)證與協(xié)調(diào)更新。以INETIS下的test節(jié)點(diǎn)為例,通過(guò)get命令獲取節(jié)點(diǎn)內(nèi)容,如圖1所示。
每當(dāng)節(jié)點(diǎn)數(shù)據(jù)內(nèi)容改變,版本號(hào)dataVersion均會(huì)增長(zhǎng),客戶端獲取數(shù)據(jù)的同時(shí)也會(huì)獲取數(shù)據(jù)版本號(hào)。節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容以原子方式讀寫(xiě),讀操作讀取全部?jī)?nèi)容,寫(xiě)操作替換全部?jī)?nèi)容,節(jié)點(diǎn)還具有一個(gè)訪問(wèn)控制列表來(lái)約束某些操作。
圖1 znode節(jié)點(diǎn)信息
Zookeeper有兩種類型的節(jié)點(diǎn):(1)臨時(shí)節(jié)點(diǎn),在創(chuàng)建該節(jié)點(diǎn)會(huì)話的存活期間存在,會(huì)話結(jié)束,臨時(shí)節(jié)點(diǎn)自動(dòng)刪除;(2)持久節(jié)點(diǎn),節(jié)點(diǎn)創(chuàng)建后一直存在,直到有刪除操作來(lái)主動(dòng)清除這個(gè)節(jié)點(diǎn)[4]。
配置管理中心以B/S方式提供給維護(hù)人員使用,可以進(jìn)行增加、更改、刪除、查看等操作。每一個(gè)配置文件均對(duì)應(yīng)一個(gè)Zookeeper中的節(jié)點(diǎn),節(jié)點(diǎn)變更會(huì)通知到注冊(cè)過(guò)該節(jié)點(diǎn)的各應(yīng)用。同時(shí)可以查看配置文件的歷史版本,便于對(duì)比,配置管理中心與各應(yīng)用的調(diào)用關(guān)系如圖2所示。
圖2 配置管理中心與各應(yīng)用的調(diào)用關(guān)系
配置管理中心以Web頁(yè)面的方式供維護(hù)人員使用,并與客票系統(tǒng)交易中間件保持連接,配置管理中心保存著INETIS、ATCTMS和CTMSX3個(gè)應(yīng)用服務(wù)的配置文件。配置中心的主要功能如下:
(1)基于Web頁(yè)面的配置文件管理。通過(guò)頁(yè)面可以查看各個(gè)服務(wù)當(dāng)前的配置文件,并檢查當(dāng)前運(yùn)行的配置文件是否與Zookeeper中的配置文件一致。同時(shí)Web界面可以連到各個(gè)集群中的服務(wù),通過(guò)后臺(tái)服務(wù)提供的接口,查看各配置項(xiàng)在內(nèi)存中的值與配置文件中是否一致。
(2)同一個(gè)APP下的多個(gè)配置文件。同一個(gè)應(yīng)用下存在多個(gè)配置文件,對(duì)配置進(jìn)行分類,對(duì)于經(jīng)常更改的,加入到Zookeeper節(jié)點(diǎn)中。并在客戶端中對(duì)該節(jié)點(diǎn)注冊(cè)watcher事件。
(3)配置文件的版本管理。生產(chǎn)中每次更改的配置文件需要進(jìn)行備份,如果升級(jí)不成功可以回退。選取Git進(jìn)行配置文件的版本管理,Web頁(yè)面查看歷史版本配置文件。
(4)數(shù)據(jù)持久化保存。當(dāng)交易中間件從統(tǒng)一配置管理中心得到數(shù)據(jù)更新后,將數(shù)據(jù)保存在配置文件中。以防Zookeeper異常時(shí),無(wú)法得到配置文件,應(yīng)用無(wú)法啟動(dòng)。
(5)實(shí)時(shí)更新。對(duì)于新獲取的配置文件,在持久化保存后,需要將更改的值重新加載入內(nèi)存替換舊的值,達(dá)到無(wú)需重啟應(yīng)用即完成配置生效的功能。
客票系統(tǒng)交易中間件的配置文件以節(jié)點(diǎn)的方式存于Zookeeper中,配置文件在Zookeeper server中節(jié)點(diǎn)的設(shè)計(jì)如圖3所示,<>表示目錄。從圖中可以看到,最上一級(jí)目錄名為middle_ware,表示客票交易中間件的目錄,它的子目錄為app_name,即CTMS、INETIS、CTMSX等。每個(gè)中間件應(yīng)用服務(wù)下有兩個(gè)子目錄,分別為conf與version,conf節(jié)點(diǎn)下的子節(jié)點(diǎn)為最終的配置文件節(jié)點(diǎn),節(jié)點(diǎn)里面的內(nèi)容即為配置文件里的值。以中間件應(yīng)用服務(wù)INETIS為例,INETIS中的配置文件gemfire.cfg在Zookeeper Server里的節(jié)點(diǎn)路徑即為/middle_ware/INETIS/CONF/gemfire,配置文件eid.cfg對(duì)應(yīng)的節(jié)點(diǎn)為/middle_ware/INETIS/CONF/eid。
客票交易中間件如CMTS、INETIS等在運(yùn)行之前,必須先加載本地配置文件,再進(jìn)行一系列參數(shù)的校驗(yàn)與初始化后才能正常啟動(dòng)。更新配置文件時(shí),需要同步兩個(gè)中心的所有服務(wù)器,確保各服務(wù)器的配置無(wú)誤后才能重啟服務(wù)。為了改進(jìn)這種更新方式,提高應(yīng)用程序維護(hù)的效率,需要解決兩個(gè)問(wèn)題。
圖3 配置文件節(jié)點(diǎn)設(shè)計(jì)
2.3.1 自動(dòng)獲取
配置文件的自動(dòng)獲取即應(yīng)用程序從Zookeeper中獲取配置文件,Zookeeper所有讀操作getdata、getchildren和exists均具有設(shè)置watch的選項(xiàng),Zookeeper 的watch事件是一次性觸發(fā)器,當(dāng)watch監(jiān)視的數(shù)據(jù)發(fā)生變化時(shí),通知設(shè)置了該watch的client,即 watcher[5]。
為了完成應(yīng)用程序從Zookeeper中自動(dòng)獲取配置文件的內(nèi)容,需要改造應(yīng)用程序,使應(yīng)用程序啟動(dòng)前讀取znode節(jié)點(diǎn)里的內(nèi)容,并且將watch事件一直注冊(cè)在該節(jié)點(diǎn)上,只要節(jié)點(diǎn)內(nèi)容有變化,作為Zookeeper客戶端的應(yīng)用將獲取數(shù)據(jù)變化事件。
2.3.2 重新加載
當(dāng)Zookeeper節(jié)點(diǎn)內(nèi)容發(fā)生變化時(shí),watch該節(jié)點(diǎn)的回調(diào)函數(shù)便會(huì)執(zhí)行。函數(shù)里實(shí)現(xiàn)了重新解析配置文件的內(nèi)容,刷新各個(gè)配置項(xiàng)在內(nèi)存中的值,便可實(shí)現(xiàn)配置文件的實(shí)時(shí)更新。同時(shí)為了防止Zookeeper服務(wù)器出現(xiàn)異常,需要將最新的配置文件持久化寫(xiě)入本地文件,以防程序重啟時(shí)因無(wú)法獲取配置文件而導(dǎo)致服務(wù)不可用,還可以進(jìn)行版本管理。
2.3.3 更新
配置文件節(jié)點(diǎn)的創(chuàng)建與更新需要開(kāi)發(fā)一個(gè)單獨(dú)的發(fā)布程序,發(fā)布程序的接口與配置文件獲取類似,區(qū)別主要在發(fā)布用的是setdata,獲取用的是getdata[6]。由于每個(gè)應(yīng)用均包括多個(gè)配置文件,在發(fā)布程序里肯定會(huì)包括全部的配置文件的加載,但有時(shí)生產(chǎn)只需要更新一個(gè)配置文件,因此在setdata之前是需要對(duì)比新的配置文件里的內(nèi)容與Zookeeper里對(duì)應(yīng)節(jié)點(diǎn)的內(nèi)容,如果兩者內(nèi)容一致,則不需要設(shè)置這個(gè)節(jié)點(diǎn),反之如果不一樣,則對(duì)這個(gè)節(jié)點(diǎn)進(jìn)行setdata。
涉及到節(jié)點(diǎn)改變的不同方式,Zookeeper可能維護(hù)兩個(gè)watch列表:節(jié)點(diǎn)的數(shù)據(jù)watch和子節(jié)點(diǎn)git的watch。getData和exists設(shè)置了內(nèi)容watch,getChildren設(shè)置了子節(jié)點(diǎn)watch,操作返回的數(shù)據(jù)類型不同,前者是節(jié)點(diǎn)的內(nèi)容,后者是節(jié)點(diǎn)的子節(jié)點(diǎn)列表[7]。
版本管理的功能在于跟蹤記錄整個(gè)配置文件的變更過(guò)程,在時(shí)間上全程跟蹤記錄工具將會(huì)自動(dòng)記錄開(kāi)發(fā)過(guò)程中的每個(gè)更改細(xì)節(jié)和不同版本,以便對(duì)不同階段的配置文件進(jìn)行差別分析,輔助協(xié)調(diào)管理維護(hù)開(kāi)發(fā)團(tuán)隊(duì)。
Git是當(dāng)前流行的版本管理工具,Git的每次提交都會(huì)根據(jù)SHA1算法生成唯一的commitid,而不是像SVN那樣對(duì)單個(gè)文件分別進(jìn)行版本更改,所以跟蹤以前某次提交的代碼時(shí),不用考慮到底提交了哪些文件,所有變動(dòng)的配置文件都會(huì)一次性的取出來(lái)。常用的 git命令有 git add,git commit,git checkout等。
對(duì)于統(tǒng)一配置管理中心的維護(hù)人員來(lái)說(shuō),顯然不希望了解版本庫(kù)里的所有信息,因此,本系統(tǒng)的目標(biāo)是對(duì)git版本庫(kù)中的配置文件信息進(jìn)行針對(duì)性的展示。在版本控制系統(tǒng)中,分支的個(gè)數(shù),提交的次數(shù),提交者以及提交的時(shí)間都是十分重要的信息,在配置文件首頁(yè)看到的是配置文件節(jié)點(diǎn)的最新提交信息。
REST包含3個(gè)主要內(nèi)容:資源,表示和狀態(tài)。資源指網(wǎng)絡(luò)上一種體現(xiàn)為比特流的實(shí)物或抽象概念,可通過(guò)統(tǒng)一資源定位符URI定位;表示指資源呈現(xiàn)的方式,為構(gòu)建可擴(kuò)展,松耦合的Web提供準(zhǔn)則;狀態(tài)是服務(wù)器端資源狀態(tài)或終端狀態(tài),資源的狀態(tài)保存在服務(wù)端,應(yīng)用的狀態(tài)由應(yīng)用自身維護(hù),由于REST所有交互都是無(wú)狀態(tài)的,因此終端的每次請(qǐng)求需要攜帶交互所需要的全部信息[8]。
REST將整個(gè)服務(wù)端抽象成資源的集合,資源由URI標(biāo)識(shí),終端調(diào)用HTTP的主要方法包括POST、DELETE、PUT及GET,可以分別對(duì)資源進(jìn)行增加、刪除,更改和查詢等操作?;赗EST實(shí)施的上述架構(gòu)約束,可輕松解決系統(tǒng)開(kāi)發(fā)中接口可擴(kuò)展性和終端異構(gòu)性等問(wèn)題。
統(tǒng)一配置管理中心給維護(hù)人員使用,根據(jù)統(tǒng)一配置中心的需求分析,其提供的主要功能有:
(1)集群中各服務(wù)的運(yùn)行狀態(tài),包括服務(wù)連接池使用大小,錯(cuò)誤日志的監(jiān)控。(2)集群中各主機(jī)的狀態(tài),包括CPU,內(nèi)存,磁盤(pán),網(wǎng)絡(luò)的利用率。(3)對(duì)各服務(wù)進(jìn)行操作,包括對(duì)服務(wù)的啟動(dòng)與停止。(4)更新或更改配置文件等功能,根據(jù)需求,通過(guò)表單提交配置項(xiàng)的值,并將新的配置信息返回給開(kāi)發(fā)人員。(5)權(quán)限管理,包括用戶角色分配、用戶登錄、注冊(cè)、添加及修改用戶基本信息等。
結(jié)合上述需求分析,遵循REST規(guī)范,設(shè)計(jì)出符合REST風(fēng)格的統(tǒng)一配置管理中心接口設(shè)計(jì),如表1所示。
表1 配置文件管理REST接口設(shè)計(jì)
為了獲得更好的可靠性服務(wù)和更快的同步速度,測(cè)試環(huán)境采用集群的方式部署Zookeeper服務(wù),通過(guò)客票交易中間件建立到ZooKeeper實(shí)例的連接,然后在服務(wù)集群中創(chuàng)建節(jié)點(diǎn),并將節(jié)點(diǎn)設(shè)置為監(jiān)聽(tīng)狀態(tài),該節(jié)點(diǎn)的內(nèi)容為交易中間件INETIS配置文件的內(nèi)容。當(dāng)維護(hù)人員需要修改INETIS配置文件內(nèi)容時(shí),只需要通過(guò)Web頁(yè)面選擇對(duì)應(yīng)的配置文件,并對(duì)文件內(nèi)容進(jìn)行修改,可以看到Zookeeper中的節(jié)點(diǎn)內(nèi)容已經(jīng)修改,而此時(shí)監(jiān)聽(tīng)了這個(gè)節(jié)點(diǎn)INETIS配置文件的最新修改時(shí)間已經(jīng)更新為當(dāng)前時(shí)間,內(nèi)容與修改后的一致。新的同步方式幾乎在秒級(jí)完成,而采用傳統(tǒng)的文件傳輸方式完成一次同步需要近10 min。
服務(wù)器增長(zhǎng)的速度已遠(yuǎn)遠(yuǎn)高于開(kāi)發(fā)人員的增長(zhǎng)速度,通過(guò)傳統(tǒng)人工手段登錄服務(wù)器實(shí)現(xiàn)配置文件的更新不僅效率低而且容易出錯(cuò),本文提出了一種基于Zookeeper的配置文件管理方案,將客票交易中間件應(yīng)用服務(wù)器眾多的配置文件集中式地存放在Zookeper節(jié)點(diǎn)上,在Zookeeper的客戶端,通過(guò)與服務(wù)端連接,可以方便快捷地獲取應(yīng)用服務(wù)器最新的配置文件,并在此基礎(chǔ)上增加了過(guò)期配置文件的備份功能。目前,該方案已經(jīng)應(yīng)用在客票系統(tǒng)雙中心,應(yīng)用結(jié)果表明,此方案不僅能保證各配置文件的一致性而且無(wú)需重啟服務(wù),整個(gè)更新在秒級(jí)完成,極大地提高了升級(jí)與維護(hù)的效率,保證了服務(wù)的不間斷運(yùn)行。Zookeeper除了這個(gè)功能外,還能管理集群中的節(jié)點(diǎn),下一步我們將繼續(xù)深入研究,持續(xù)提高系統(tǒng)的可靠性。