胡喜明,胡 淼,夏夢瑩,周慧敏
(杭州電子科技大學(xué) 通信工程學(xué)院,浙江 杭州 310018)
RPC是當(dāng)前分布式架構(gòu)中重要的組成部分[1,2]。多個服務(wù)通過RPC框架以XML、JSON等形式進(jìn)行數(shù)據(jù)交互,降低整體系統(tǒng)的耦合性,而注冊中心是保證RPC服務(wù)間可靠通信不可或缺的組件[3]。WebService是實現(xiàn)注冊中心的一種方式,其內(nèi)部采用SOAP協(xié)議實現(xiàn)服務(wù)間通信。SOAP底層應(yīng)用XML格式進(jìn)行數(shù)據(jù)傳輸,在傳輸?shù)倪^程中需要額外標(biāo)簽的支持,而隨著SOAP協(xié)議的完善,傳輸中所需要的標(biāo)簽數(shù)量也在持續(xù)增加,使得WebService傳輸帶寬增加并且降低了系統(tǒng)的傳輸效率[4,5]。
當(dāng)前主流系統(tǒng)中多采用Zookeeper作為注冊中心,內(nèi)部以字節(jié)數(shù)組的形式對注冊信息進(jìn)行存儲,解決了SOAP中帶寬需求增加的問題。但是Zookeeper存在以下問題:首先,在集群部署的情況下,Master節(jié)點宕機(jī)時的選舉機(jī)制一般需要耗時30 s-120 s,在此期間所有服務(wù)均不可用。其次,Zookeeper缺少可視化界面管理,無法對服務(wù)進(jìn)行細(xì)粒度治理。最后,Zookeeper運行時受到系統(tǒng)內(nèi)存的限制,運行中不斷產(chǎn)生的數(shù)據(jù)會使可用內(nèi)存不斷減少,進(jìn)而導(dǎo)致整體系統(tǒng)性能降低[6]。
本文提出了一種基于REST風(fēng)格的注冊中心系統(tǒng)(mRegistry)。項目中采用REST替代SOAP作為對外接口風(fēng)格,REST傳輸內(nèi)容以及操作方式更為簡潔,其內(nèi)部實現(xiàn)了跨語言訪問功能,有效解決SOAP傳輸冗余的問題[7]。系統(tǒng)采用FreeMaker、Springboot和Mybatis框架[8],搭建了可視化后端管理頁面,實現(xiàn)服務(wù)細(xì)粒度控制。內(nèi)置數(shù)據(jù)持久化方案保證服務(wù)系統(tǒng)的穩(wěn)定高效。通過與SOAP注冊中心對比,該系統(tǒng)具有更好的并發(fā)處理能力。
注冊中心是RPC系統(tǒng)的核心組件,其承載著連接服務(wù)提供者與服務(wù)消費者的任務(wù)[9]。一個完整的注冊中心應(yīng)具備功能如下:
(1)服務(wù)注冊表功能:服務(wù)注冊表是記錄當(dāng)前各個服務(wù)的信息,例如服務(wù)的名稱、ip、地址等。服務(wù)注冊表需要提供服務(wù)增加、查詢、修改、移除的功能;
(2)服務(wù)發(fā)現(xiàn)與注冊:第三方應(yīng)用在接入注冊中心項目后,對注冊的應(yīng)用進(jìn)行保存,并開放查詢的API功能;
(3)服務(wù)監(jiān)控:注冊中心需要對服務(wù)進(jìn)行定時檢測,若發(fā)現(xiàn)服務(wù)長時間無法訪問,應(yīng)該自動對服務(wù)進(jìn)行清除;
如圖1所示為mRegistry注冊中心體系結(jié)構(gòu)圖。mRe-gistry 服務(wù)注冊中心主要包括客戶端遠(yuǎn)程API接口以及后臺管理中心。Java項目可通過引入對應(yīng)maven依賴并配置相關(guān)參數(shù)實現(xiàn)自動化服務(wù)管理功能,非java語言或者未接入該系統(tǒng)的java程序可通過自定義REST風(fēng)格API接口實現(xiàn)服務(wù)的注冊、發(fā)現(xiàn)、監(jiān)控功能。注冊中心在接收到服務(wù)的注冊信息后通過內(nèi)部線程化機(jī)制將信息寫入到Mysql數(shù)據(jù)庫中,隨后會定時輪循保存到本地磁盤。
圖1 mRegistry體系結(jié)構(gòu)
mRegistry注冊中心為管理員提供了完備的后臺管理頁面,通過調(diào)用內(nèi)部接口可查看當(dāng)前提供的服務(wù)數(shù)以及注冊信息,并實現(xiàn)對當(dāng)前服務(wù)的添加、修改、查看等功能。接下來針對mRegistry注冊中心中服務(wù)接口以及架構(gòu)設(shè)計進(jìn)行詳細(xì)分析。
mRegistry系統(tǒng)在收到注冊/更新請求后需要對當(dāng)前服務(wù)進(jìn)行數(shù)據(jù)庫更新以及本地磁盤存儲。項目中采用3個實體類分別對應(yīng)數(shù)據(jù)庫中3張表結(jié)構(gòu),見表1~表3,m_re-gister 表主要搭載在管理頁面,可通過管理員后臺對其進(jìn)行編輯修改。m_register_data表主要記錄當(dāng)前運行中的注冊信息,在服務(wù)停止后通過異步處理的方式清除無效的服務(wù),同時更新m_register表中的地址信息。m_register_message表主要作為變更操作記錄表,系統(tǒng)將服務(wù)變更信息存入表中作為當(dāng)前操作記錄,內(nèi)部通過線程化機(jī)制定時檢測當(dāng)前表中是否存在數(shù)據(jù),在檢測到記錄表中的數(shù)據(jù)后,會按順序?qū)⒆兏畔⒏碌奖镜卮疟P,保證本地數(shù)據(jù)與數(shù)據(jù)庫一致。
表1 m_register歷史注冊信息
表2 m_register_data當(dāng)前服務(wù)注冊信息
表3 m_register_message信息更改記錄
mRegistry對外提供了基于REST風(fēng)格的API調(diào)用接口,REST采用面向資源協(xié)議實現(xiàn)資源抽象化,并通過統(tǒng)一資源標(biāo)志符(uniform resource locator,URI)以及 HTTP 規(guī)范所定義的GET、POST、PUT、DELETE實現(xiàn)資源的訪問。其操作方式更為簡潔,充分發(fā)揮了HTTP訪問的特性。由于REST內(nèi)置了跨語言訪問功能,非JAVA項目以及未接入該系統(tǒng)的JAVA項目也可以實現(xiàn)接口的訪問。為保證開放性接口的安全性,接口調(diào)用中需要設(shè)置相應(yīng)的令牌進(jìn)行權(quán)限校驗,防止外部非法訪問。如圖2所示,注冊中心對外提供服務(wù)注冊與續(xù)約、服務(wù)發(fā)現(xiàn)、服務(wù)下線、服務(wù)監(jiān)控的功能。
圖2 外部API功能結(jié)構(gòu)
(1)服務(wù)注冊與續(xù)約
系統(tǒng)啟動后,服務(wù)提供者會向注冊中心發(fā)送注冊請求,請求的內(nèi)容包括校驗令牌、服務(wù)訪問地址以及業(yè)務(wù)名稱。注冊中心收到JSON格式數(shù)據(jù)后,通過Jackson序列化工具將數(shù)據(jù)反序列化為輸出對象。系統(tǒng)調(diào)用內(nèi)部驗證方法對數(shù)據(jù)進(jìn)行格式以及令牌權(quán)限的校驗,校驗不通過返回權(quán)限不足的提示信息。對于通過校驗的數(shù)據(jù),為保證在高并發(fā)模式下的接口安全性,服務(wù)內(nèi)部采用Volatile關(guān)鍵字聲明的阻塞隊列registryQueue進(jìn)行數(shù)據(jù)保存,該隊列底層采用JAVA多線程的ReetrantLock鎖機(jī)制,保證數(shù)據(jù)在高并發(fā)下的線程安全。為保證服務(wù)響應(yīng)性能,數(shù)據(jù)存儲到registryQueue隊列后并非直接進(jìn)行持久化存儲,而是等待內(nèi)部線程進(jìn)行處理。系統(tǒng)可通過異步回調(diào)數(shù)據(jù)向客戶端返回注冊成功信息,不需要等待內(nèi)部完成注冊。
(2)服務(wù)的發(fā)現(xiàn)
服務(wù)消費者向mRegistry發(fā)送服務(wù)發(fā)現(xiàn)請求,通過傳入服務(wù)注冊的KEY、業(yè)務(wù)標(biāo)識、環(huán)境標(biāo)識來唯一的確定所需要的服務(wù)。同服務(wù)注冊相同,需要先對數(shù)據(jù)進(jìn)行反序列化以及格式校驗。由于數(shù)據(jù)最終將持久化同步到本地磁盤,因此系統(tǒng)會采用服務(wù)注冊的KEY、業(yè)務(wù)標(biāo)識、環(huán)境標(biāo)識生成文件存儲路徑,通過JAVA文件流將文件信息從本地磁盤加載到內(nèi)存中,最終將數(shù)據(jù)以KEY-VALUE形式返回,其中KEY為服務(wù)參數(shù)名,VALUE對應(yīng)服務(wù)提供者所提供的接口信息列表。該接口主要針對非JAVA項目以及未接入該項目的程序進(jìn)行臨時調(diào)用。為提高響應(yīng)速度,采用 redis 對查詢數(shù)據(jù)進(jìn)行緩存,并設(shè)置相應(yīng)的過期時間。當(dāng)下一次查詢相同服務(wù)時可直接從redis中獲取,減少磁盤訪問次數(shù)。
(3)服務(wù)下線
服務(wù)下線功能是服務(wù)提供者主動向注冊中心提交的下線請求。通過傳入的業(yè)務(wù)標(biāo)識,業(yè)務(wù)地址以及服務(wù)名稱唯一的確定所要下線的服務(wù)。在接口通過校驗后,系統(tǒng)內(nèi)部采用Volatile關(guān)鍵字聲明的removeQueue隊列,將通過校驗后的信息加入到隊列中,后續(xù)交給內(nèi)部線程去執(zhí)行下線操作。
(4)服務(wù)監(jiān)控
該接口主要用在調(diào)用注冊請求時監(jiān)控當(dāng)前服務(wù)是否更新地址信息。服務(wù)調(diào)用者傳入業(yè)務(wù)標(biāo)識、地址以及服務(wù)名稱進(jìn)行接口調(diào)用。該接口會應(yīng)用Spring框架中的DeferredResult類作為返回值,該類主要為了處理耗時操作,在沒有超過所設(shè)置的時間范圍或者未調(diào)用setResult方法時,接口不返回。系統(tǒng)通過異步請求的形式設(shè)置相應(yīng)的心跳時間對監(jiān)聽的接口進(jìn)行檢測,同時將信息存儲在key-value所表示的Map中。系統(tǒng)每次調(diào)用心跳接口時調(diào)用方都會主動阻塞10 s,直至阻塞超時或服務(wù)注冊信息變動時響應(yīng)。該接口為自動化管理提供心跳服務(wù)。
對外接口處理模塊主要針對REST接口所注冊的服務(wù)進(jìn)行存儲、更新以及實時監(jiān)控操作。為了提高系統(tǒng)的整體性能,該模塊采用并發(fā)編程思想中的線程池技術(shù),在不影響主線程運行的情況下實現(xiàn)內(nèi)部操作線程化,提高系統(tǒng)響應(yīng)速度。其中主要分為服務(wù)注冊處理、服務(wù)下線處理、檢測服務(wù)更新以及心跳檢測。
(1)服務(wù)注冊處理
在2.2節(jié)的服務(wù)注冊API中可以看到,當(dāng)調(diào)用對外開放接口后數(shù)據(jù)將存儲在registryQueue隊列中,為了保證數(shù)據(jù)庫中數(shù)據(jù)的一致性,采用線程池技術(shù)開啟多個線程對隊列中的數(shù)據(jù)進(jìn)行處理。服務(wù)注冊處理流程如下,系統(tǒng)通過registryQueue隊列獲取當(dāng)前隊列存儲數(shù)據(jù),若隊列為空則進(jìn)行下一個循環(huán)繼續(xù)監(jiān)聽隊列,否則將隊列中的數(shù)據(jù)存儲到數(shù)據(jù)庫中。添加完成后將該服務(wù)狀態(tài)從本地磁盤中讀取出來,對服務(wù)的注冊信息進(jìn)行封裝并與Mysql數(shù)據(jù)庫中數(shù)據(jù)作對比,將產(chǎn)生變化的信息存入m_registry_message中等待后續(xù)本地磁盤數(shù)據(jù)同步。
(2)服務(wù)下線處理
為降低服務(wù)響應(yīng)的延時,服務(wù)下線階段同樣采用線程池技術(shù),開啟多個線程進(jìn)行輪循處理。需要做下線操作的服務(wù)信息均存儲在2.2節(jié)所提到的removeQueue隊列中,系統(tǒng)會輪循檢測隊列是否存在信息,將檢測到的信息與數(shù)據(jù)庫進(jìn)行對比并移除對應(yīng)服務(wù)。服務(wù)移除后需要對在m_registry_message表中記錄當(dāng)前操作信息,等等后續(xù)線程處理。
(3)檢測服務(wù)更新處理
服務(wù)更新檢測是為了將服務(wù)注冊以及服務(wù)下線的數(shù)據(jù)進(jìn)行本地磁盤同步。當(dāng)前服務(wù)中更新的數(shù)據(jù)都存儲在 m_registry_message 表中,系統(tǒng)首先會對數(shù)據(jù)庫表中數(shù)據(jù)進(jìn)行獲取,將獲取到的數(shù)據(jù)進(jìn)行狀態(tài)監(jiān)測,對于鎖定的服務(wù)將地址置空。系統(tǒng)將監(jiān)測后的數(shù)據(jù)按順序進(jìn)行本地磁盤同步。該功能中為保證客戶端服務(wù)查詢的可靠性,采用廣播的形式對客戶進(jìn)行通知服務(wù),線程的輪詢操作為用戶提供了秒級通知的效果。在變更信息的同時會對數(shù)據(jù)庫中過期信息進(jìn)行清理,使得外部監(jiān)控接口在監(jiān)測到數(shù)據(jù)更改時可以得到正確的返回結(jié)果。
(4)心跳檢測處理
服務(wù)注冊處理線程中應(yīng)用registryQueue與線程池技術(shù)進(jìn)行服務(wù)的注冊,在檢測到當(dāng)前服務(wù)信息存在時,將會對注冊時間進(jìn)行更新,保證當(dāng)前注冊信息的有效性。注冊中心內(nèi)部設(shè)置心跳檢測時間,若數(shù)據(jù)庫中時間與心跳時間的總和小于當(dāng)前時間即可認(rèn)為當(dāng)前服務(wù)已經(jīng)失效,此時需要清除 m_registry_data表中的信息。為了保證在調(diào)用服務(wù)發(fā)現(xiàn)API時,本地數(shù)據(jù)查詢到最新的數(shù)據(jù),在清除表中信息后需要對當(dāng)前操作進(jìn)行本地磁盤同步處理。
如圖3所示,后臺管理中心主要分為服務(wù)展示、服務(wù)管理以及使用說明3部分。管理員通過輸入賬號密碼實現(xiàn)后臺的登錄,為保證服務(wù)的安全性系統(tǒng),系統(tǒng)采用MD5加密模式對輸入賬號進(jìn)行校驗。登陸成功后系統(tǒng)生成對應(yīng)Token令牌存儲在Redis中并返回前端,每次在操作管理界面功能時都需要進(jìn)行令牌校驗。該存儲模式主要為了實現(xiàn)單點登錄功能以及解決集群環(huán)境下的Session不一致現(xiàn)象。圖4為登錄成功后顯示的后臺管理頁面,在運行報表標(biāo)簽中可以查看當(dāng)前系統(tǒng)中正在運行的注冊服務(wù)數(shù)量以及當(dāng)前系統(tǒng)注冊的人員數(shù)量,方便管理人員進(jìn)行數(shù)據(jù)統(tǒng)計。服務(wù)注冊標(biāo)簽為該后臺管理的核心功能,其中主要包括對服務(wù)的增加、修改、刪除以及禁用功能,管理員還可以通過輸入業(yè)務(wù)標(biāo)識、環(huán)境標(biāo)識以及注冊的key進(jìn)行服務(wù)的精確查找。在使用教程界面中主要對該系統(tǒng)的功能點進(jìn)行了描述,同時還提供了完整的使用說明,方便管理人員使用。
圖3 后臺管理功能結(jié)構(gòu)
圖4 系統(tǒng)管理員界面
目前傳統(tǒng)Web頁面設(shè)計主要采用HTML+CSS+JSP框架。JSP功能比較強(qiáng)大,可以在頁面上編寫處理邏輯代碼,但隨著頁面功能的擴(kuò)展,邏輯代碼的復(fù)雜度提高,且在第一次執(zhí)行的時候還需要進(jìn)行編譯轉(zhuǎn)換操作,增加了系統(tǒng)的維護(hù)難度。項目中采用FreeMaker模板引擎技術(shù),該技術(shù)主要用在MVC模型中,遵循模板+數(shù)據(jù)=頁面的形式,模板只負(fù)責(zé)數(shù)據(jù)在頁面中的表現(xiàn),不涉及任何的邏輯代碼,而所有的邏輯都是由數(shù)據(jù)模型來處理。用戶最終看到的輸出是模板和數(shù)據(jù)模型合并后的結(jié)果,真正實現(xiàn)了前后端分離開發(fā)。應(yīng)用模板引擎技術(shù)開發(fā)提高了代碼復(fù)用率以及頁面的加載速度[10,11]。
對于接入mRegistry的RPC框架,直接調(diào)用對外API接口無法實現(xiàn)自動化服務(wù)上下線通知功能,因此在項目中封裝了客戶端輔助類,該類將遠(yuǎn)程API接口封裝為服務(wù)注冊、發(fā)現(xiàn)、移除方法,使得RPC框架在接入注冊中心時可以自動對服務(wù)進(jìn)行更新。并且該類內(nèi)部使用Redis對服務(wù)注冊信息進(jìn)行緩存,避免在服務(wù)發(fā)現(xiàn)時的多次IO操作。
功能的實現(xiàn)分為兩部分:
(1)系統(tǒng)啟動后在后臺服務(wù)端開啟一個服務(wù)注冊相關(guān)的守護(hù)線程,該線程可以保證在客戶端關(guān)閉連接時也進(jìn)行關(guān)閉處理。線程對接收到的服務(wù)注冊信息進(jìn)行輪循處理,將數(shù)據(jù)每隔10 s進(jìn)行數(shù)據(jù)庫更新,這里主要更新該注冊信息的updateTime字段,該字段為后續(xù)服務(wù)下線做預(yù)處理;
(2)在開啟服務(wù)注冊線程的同時也采用守護(hù)線程的模式開啟服務(wù)發(fā)現(xiàn)線程,保證服務(wù)結(jié)束后線程的釋放。服務(wù)在第一次調(diào)用服務(wù)發(fā)現(xiàn)方法時會將當(dāng)前服務(wù)信息的服務(wù)名稱作為key服務(wù)地址作為value存入Redis中并設(shè)置過期時間,后續(xù)的查詢操作均不需要進(jìn)行本地磁盤查詢,可通過服務(wù)名稱從Redis中獲取對應(yīng)地址。為防止過快訪問導(dǎo)致性能下降,會先判斷Redis變量中數(shù)據(jù)是否存在,若沒有數(shù)據(jù)則將線程暫停3 s。在檢測Redis中存在服務(wù)信息后,通過編寫REST風(fēng)格的HTTP請求訪問服務(wù)監(jiān)控API。對外服務(wù)監(jiān)控API中設(shè)置了最長等待時間為30 s,HTTP在調(diào)用監(jiān)控API接收到返回結(jié)果時,如果為FALSE,則讓當(dāng)前線程休眠10 s再次進(jìn)行調(diào)用,避免失敗重試請求次數(shù)過多。由于10 s的睡眠時間限制,在經(jīng)過3次心跳檢測訪問后如果當(dāng)前監(jiān)控API回復(fù)默認(rèn)響應(yīng)則表示當(dāng)前服務(wù)已經(jīng)停止,此時數(shù)據(jù)庫中該服務(wù)的數(shù)據(jù)在時間上已經(jīng)符合刪除條件,即心跳時間與服務(wù)UpdateTime字段的時間總和小于當(dāng)前時間。系統(tǒng)通過調(diào)用服務(wù)查詢API,刷新當(dāng)前Redis中的數(shù)據(jù),自動將下線數(shù)據(jù)移除。系統(tǒng)循環(huán)執(zhí)行上述操作,在提高整體查詢服務(wù)的速度的同時實現(xiàn)服務(wù)的自動化管理。
Redis進(jìn)行服務(wù)緩存時容易出現(xiàn)緩存雪崩的情況,主要原因是大量的服務(wù)緩存數(shù)據(jù)在同一時間過期失效,此時大量請求直接訪問數(shù)據(jù)庫導(dǎo)致數(shù)據(jù)庫無法承受當(dāng)前壓力而出現(xiàn)性能下降甚至崩潰。系統(tǒng)通過對key值設(shè)置不同的緩存時間來解決該問題,通過Random函數(shù)在原始默認(rèn)緩存時間的基礎(chǔ)上添加隨機(jī)數(shù),使得注冊的服務(wù)在內(nèi)存中的失效時間散列化。
集群化部署可以提升系統(tǒng)的容災(zāi)以及高可用能力,在分布式系統(tǒng)中注冊中心均需要以集群的形式搭建。如圖5所示,項目中采用 Nginx搭建注冊中心集群,通過更改Nginx配置文件文件中的upstream屬性為不同的注冊中心分配地址[12-14]。通過Nginx內(nèi)置的負(fù)載均衡策略為不同的端口設(shè)置權(quán)重,實現(xiàn)后臺服務(wù)器負(fù)載的均衡分配。在該模式下若當(dāng)前訪問的注冊中心出現(xiàn)宕機(jī)情況,Nginx會對節(jié)點進(jìn)行自動切換,解決了Zookeeper集群模式選舉時間過長導(dǎo)致的服務(wù)不可用問題。
圖5 nginx集群框架
在搭建集群時需保證連接相同的數(shù)據(jù)庫實例,同時多個注冊中心的管理員界面登陸賬號的配置需要保持一致。在多臺服務(wù)器同時操作同一個數(shù)據(jù)庫時,數(shù)據(jù)庫中采用聯(lián)合唯一索引的方式,最終只有一臺服務(wù)器成功執(zhí)行,保證了數(shù)據(jù)冪等性。
mRegistry系統(tǒng)采用集群方式搭建,多個注冊中心共同操作同一數(shù)據(jù)庫實例時會產(chǎn)生數(shù)據(jù)存入本地磁盤不一致的現(xiàn)象。為解決mRegistry中數(shù)據(jù)一致性問題,項目基于Raft原理,采用統(tǒng)一處理操作變更請求。其作用是為了保證節(jié)點之間操作的日志副本一致,并通過邏輯時鐘進(jìn)行定時保存,保證節(jié)點運行狀態(tài)機(jī)得到一致的結(jié)論[15]。項目中m_registry_message消息表作為統(tǒng)一處理分發(fā)變更請求,僅在變更數(shù)據(jù)時才產(chǎn)生消息,消息量相對較少,并且消息輪詢線程存在時間間隔,因此數(shù)據(jù)庫中消息表的壓力也不會過大。在服務(wù)提供者進(jìn)行注冊以及修改服務(wù)時,m_registry_message表會將注冊的操作進(jìn)行記錄,以順序遍歷的方式同步到本地磁盤,遍歷后清除消息表中相應(yīng)數(shù)據(jù),保證本地數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)一致,并內(nèi)置周期性的將數(shù)據(jù)庫中注冊信息全量同步到本地磁盤,保證多個注冊中心節(jié)點的數(shù)據(jù)一致性。
在本地電腦搭建注冊中心環(huán)境,項目啟動后訪問http://localhost:8080/admin進(jìn)入登陸頁面,如圖6所示為輸入正確賬號密碼后進(jìn)入的后臺管理界面。管理員可以通過瀏覽器便捷地查看系統(tǒng)當(dāng)前服務(wù)數(shù),并通過頁面上的功能按鍵進(jìn)行服務(wù)的新增、查詢、修改和刪除操作。測試結(jié)果可知,該界面運行流暢,人機(jī)交互效果良好,符合預(yù)期設(shè)計需求。
圖6 后臺服務(wù)注冊管理界面
針對服務(wù)注冊以及查詢功能,需要在客戶端編寫服務(wù)注冊以及查詢的代碼,代碼中調(diào)用自定義的客戶端類發(fā)送服務(wù)注冊請求。如圖7所示,客戶端開啟后可以從控制臺看到服務(wù)注冊成功的日志信息,并且系統(tǒng)每隔10 s會向mRegistry發(fā)出監(jiān)控請求,檢測當(dāng)前注冊服務(wù)是否存在。測試代碼中設(shè)置2 s的睡眠后進(jìn)行服務(wù)查詢,從圖中可知此時客戶端編寫的服務(wù)發(fā)現(xiàn)代碼成功獲取到了當(dāng)前注冊的服務(wù)信息。
圖7 啟動后日志
通過對數(shù)據(jù)庫中key為update的服務(wù)進(jìn)行修改,測試服務(wù)自動化管理功能。修改update服務(wù)的地址,等待幾秒鐘后系統(tǒng)基于心跳檢測機(jī)制發(fā)現(xiàn)當(dāng)前注冊服務(wù)信息與實際注冊不符,系統(tǒng)將注冊表中信息清除并重新將當(dāng)前服務(wù)注冊。如圖8所示,此時在服務(wù)端做出了服務(wù)更改的操作,需要在m_registry_message表中記錄一條JSON格式的變更信息。系統(tǒng)內(nèi)部通過對記錄表中數(shù)據(jù)進(jìn)行監(jiān)聽將當(dāng)前更改操作寫入到本地磁盤中并將該條記錄刪除。至此完成了自動化管理的功能。
圖8 m_registry_message表
這一部分主要針對mRegistry注冊中心和SOAP注冊中心的響應(yīng)性能進(jìn)行測試。通過maven插件對注冊中心項目進(jìn)行打包,將打包好的JAR文件分別上傳到服務(wù)器中。服務(wù)啟動前需要在mysql數(shù)據(jù)庫中創(chuàng)建mRegistry對應(yīng)表結(jié)構(gòu),并對redis進(jìn)行相應(yīng)的部署。mRegistry注冊中心需要對注冊的服務(wù)進(jìn)行本地磁盤保存,應(yīng)根據(jù)不同系統(tǒng)修改對應(yīng)存儲路徑信息。測試中選取3臺服務(wù)器,其中兩臺服務(wù)器分別部署基于SOAP風(fēng)格的注冊中心和mRegistry注冊中心,第3臺作為模擬請求。3臺機(jī)器配置見表4。
表4 服務(wù)器配置
實驗中采用并發(fā)測試工具Jmeter對兩個注冊中心系統(tǒng)進(jìn)行性能壓力測試。Jmeter模擬高并發(fā)下服務(wù)注冊與服務(wù)查詢請求,其內(nèi)部通過多線程機(jī)制設(shè)置并發(fā)訪問數(shù)量,根據(jù)并發(fā)數(shù)的不同對比兩個注冊中心數(shù)據(jù)響應(yīng)速度。
3.2.1 服務(wù)注冊
如圖9所示為客戶端并發(fā)模擬服務(wù)注冊請求的響應(yīng)時間對比圖,橫坐標(biāo)為并發(fā)用戶數(shù)量,縱坐標(biāo)為平均響應(yīng)時間。由圖可知,在并發(fā)數(shù)量較小的情況下兩者的服務(wù)注冊時間相近。隨著并發(fā)訪問量的提升,SOAP服務(wù)注冊中心響應(yīng)時間遠(yuǎn)大于mRegistry,可以看出在服務(wù)注冊方面mRegistry有明顯的性能優(yōu)勢。
圖9 注冊服務(wù)響應(yīng)時間對比
3.2.2 服務(wù)發(fā)現(xiàn)
測試過服務(wù)注冊功能后,兩個注冊中心所注冊的服務(wù)數(shù)量相同??蛻舳四M高并發(fā)情況下服務(wù)發(fā)現(xiàn)請求,如圖10為服務(wù)發(fā)現(xiàn)功能的并發(fā)訪問數(shù)量與平均響應(yīng)時間關(guān)系圖,從實驗結(jié)果可以看到,SOAP注冊中心的響應(yīng)時間始終高于REST注冊中心。隨著并發(fā)訪問量的提高,兩者的響應(yīng)時間差依然很大,最終SOAP服務(wù)注冊中心響應(yīng)時間接近mRegistry響應(yīng)時間兩倍。從曲線的走勢可以看出mRegistry更加平穩(wěn),這說明mRegistry系統(tǒng)在高并發(fā)環(huán)境下更加穩(wěn)定。
圖10 服務(wù)發(fā)現(xiàn)響應(yīng)時間對比
通過分析SOAP中xml格式傳輸存在的問題,設(shè)計了一種基于REST風(fēng)格的輕量級注冊中心。該系統(tǒng)對外開放REST風(fēng)格接口實現(xiàn)跨語言調(diào)用,同時降低了傳輸?shù)娜哂喽?;基于線程池技術(shù)對底層業(yè)務(wù)代碼進(jìn)行封裝,提高了注冊中心的運行效率;系統(tǒng)采用Redis對服務(wù)進(jìn)行緩存,降低數(shù)據(jù)庫訪問壓力,提升響應(yīng)性能;通過對API接口封裝,實現(xiàn)自動化服務(wù)管理以及心跳檢測功能;系統(tǒng)基于Raft原理防止數(shù)據(jù)重復(fù)消費,保證了數(shù)據(jù)的一致性;最后,通過與SOAP注冊中心對比可知該框架具有良好的并發(fā)處理能力。