任軍鋒,孟亞旗
(上海工業(yè)自動化儀表研究院有限公司,上海 200233)
隨著數(shù)據(jù)信息化發(fā)展速度的加快,產(chǎn)生了很多全文本類的大數(shù)據(jù)場景。對于這些數(shù)據(jù)的精準(zhǔn)、快速查詢,已成為常規(guī)需求[1]。由于數(shù)據(jù)量大,數(shù)據(jù)集中在一個中心,會給后期的業(yè)務(wù)查詢帶來巨大壓力。分布式存儲-查詢是解決這類問題的常用解決方案。存儲和查詢是分布式查詢的必要步驟,只有合適的數(shù)據(jù)存儲結(jié)構(gòu)和良好的查詢框架相配合,才能組建高效、準(zhǔn)確的查詢系統(tǒng)。同時,分布式查詢的整體架構(gòu)設(shè)計必須有較好的擴展性,即使數(shù)據(jù)量增大,也可以通過增加硬件設(shè)備、擴展存儲節(jié)點的方式解決數(shù)據(jù)查詢的性能問題[2]。
數(shù)據(jù)的存儲與查詢是前端業(yè)務(wù)的基礎(chǔ)。系統(tǒng)程序的高內(nèi)聚、低耦合,是系統(tǒng)的必要屬性。高內(nèi)聚可以讓模塊部分專注于模塊本身,重要核心內(nèi)容對外界透明,而又不依賴于外部。低耦合則是盡可能減少和外部模塊的聯(lián)系,接口設(shè)計越簡單,協(xié)同開發(fā)的效率越能大幅提升[3]。
RabbitMQ是典型的前后端通信的消息隊列通道。SocketServer可以應(yīng)對多連接的TCP/UDP請求。這兩者的結(jié)合,能夠為解決分布式查詢問題提供有效幫助。本文通過對分布式查詢軟件架構(gòu)的設(shè)計和開發(fā)的研究,為解決類似查詢?nèi)念悢?shù)據(jù)問題提供了有效參考。
文本類數(shù)據(jù)的可追溯查詢:文本類數(shù)據(jù)經(jīng)過預(yù)處理和分析關(guān)聯(lián)后,形成結(jié)構(gòu)化的信息,存儲到關(guān)系型數(shù)據(jù)庫中。Web業(yè)務(wù)端可根據(jù)提取的結(jié)構(gòu)化的內(nèi)容追溯到原始文本數(shù)據(jù),供頁面顯示原始數(shù)據(jù)詳情[4]。滿足該需求需要分5步實現(xiàn)。①原始數(shù)據(jù)文件存儲:為了更好地利用磁盤資源、減少數(shù)據(jù)庫內(nèi)容的占用量,原始數(shù)據(jù)采用本地或者中心集中壓縮存儲的方式。②結(jié)構(gòu)化數(shù)據(jù)和原始文件關(guān)聯(lián)性:結(jié)構(gòu)化數(shù)據(jù)字段中記錄原始文件路徑和位置。③分布式架構(gòu)設(shè)計的擴展性:采用QueryAgent和QueryService的二級架構(gòu)。④前后端通信接口:選擇性能健壯、耦合度低的通信服務(wù)接口。⑤查詢并發(fā)和性能:采用高并發(fā)異步的處理模型,增加索引緩存設(shè)計[5]。
RabbitMQ是一套開源(mozilla public license,MPL)的消息隊列服務(wù)軟件,采用以高性能、健壯以及可伸縮性而聞名的 Erlang 寫成[6]。軟件系統(tǒng)的前端和后端可以通過該消息隊列傳遞數(shù)據(jù),降低前后端耦合度。RabbitMQ的具體特點包括高可靠性、靈活路由、擴展性強、高可用性、多種協(xié)議多語言支持等[7]。它的五種模式為simple、work、fanout、route、topic。根據(jù)現(xiàn)有需求,路由模式更適合場景。Web業(yè)務(wù)端發(fā)送消息到交換機exchange,同時要指定route路由的key。此時,數(shù)據(jù)獲取端將queue隊列綁定到交換機exchange,同時也需要綁定到route路由的key。后端從隊列中取出消息后,分析消息內(nèi)容和查詢條件,然后下發(fā)消息到指定的查詢服務(wù)節(jié)點即可[8]。
SocketServer是用于創(chuàng)建網(wǎng)絡(luò)服務(wù)器的python標(biāo)準(zhǔn)庫常用模塊。該模塊是一個基本的socket服務(wù)器框架,使用threading處理多客戶端連接,使用seletor處理高并發(fā)訪問[9]。SocketServer剛好滿足了QueryService功能實現(xiàn)的要求。當(dāng)有多個查詢?nèi)蝿?wù)發(fā)布到同一臺QueryService節(jié)點時,查詢?nèi)蝿?wù)不會因此阻塞。SocketServer的異步機制不僅可以很好地應(yīng)對多客戶連接查詢的要求,而且實現(xiàn)過程對使用者透明,開發(fā)者僅需關(guān)注自身業(yè)務(wù)層數(shù)據(jù)內(nèi)容。
系統(tǒng)架構(gòu)如圖1所示。
圖1 系統(tǒng)架構(gòu)圖
從圖1可以清晰地看到,整個系統(tǒng)分為Web業(yè)務(wù)層、QuerAgent代理層和QueryService服務(wù)層。Web服務(wù)器通過RabbitMQ通道將查詢條件發(fā)送給QueryAgent代理層。QueryAgent根據(jù)查詢條件和規(guī)則查找算法,找到數(shù)據(jù)所在的QueryService機器。QueryService根據(jù)查詢條件,將本地存儲的原始日志信息通過socket反饋給QueryAgent代理層。QueryAgent代理層將查詢結(jié)果按照通信接口要求重新組織,發(fā)送到RabbitMQ中。Web服務(wù)器從RabbitMQ中提取信息,然后在頁面顯示。
另外,以上架構(gòu)的層次設(shè)計可以保證程序有較好的擴展性。當(dāng)數(shù)據(jù)量增加,只需增加相應(yīng)的QueryService數(shù)量,即可滿足一般的擴展需求。QueryAgent代理層的設(shè)計,也讓系統(tǒng)的擴展性更加豐富。例如,可以安裝多個查詢代理,分別查詢、處理不同業(yè)務(wù)類型的數(shù)據(jù)。Web業(yè)務(wù)層、QueryAgent層和QueryService層都可以設(shè)計各自的緩存機制,從多個方面提高查詢的效率。
①索引設(shè)計。
對于待查詢的數(shù)據(jù)的索引,設(shè)計的合理性將直接影響查詢的效率。雖然沒有萬能的索引設(shè)計公式,但是好的索引結(jié)構(gòu)都具有唯一性、分層分塊存儲、支持增量索引的特點[10]。因此,必須密切結(jié)合具體的業(yè)務(wù)場景,分析業(yè)務(wù)自身特點,找到系統(tǒng)本身的共性和個性,設(shè)計最適合自身業(yè)務(wù)的索引結(jié)構(gòu)。例如:該分布式數(shù)據(jù)查詢系統(tǒng)是用于追溯查詢原始文本數(shù)據(jù)的。原始全文本類數(shù)據(jù)經(jīng)過處理分析結(jié)構(gòu)化后存入數(shù)據(jù)庫表。前端業(yè)務(wù)層可以通過結(jié)構(gòu)化的數(shù)據(jù)庫表直接查找到原始文本類內(nèi)容,以校驗結(jié)構(gòu)化處理的準(zhǔn)確性。所以在處理結(jié)構(gòu)化數(shù)據(jù)時,就將該條原始數(shù)據(jù)的位置信息作為結(jié)構(gòu)化數(shù)據(jù)的一個字段記錄下來,作為后續(xù)精確查找的條件。
②緩存機制。
對于查詢系統(tǒng),良好的緩存設(shè)計可以大幅提高查詢效率、提升用戶體驗。緩存設(shè)計的核心是命中率高、復(fù)用性強、占用空間少。例如:本系統(tǒng)的緩存設(shè)計在QueryAgent處,查詢條件作為緩存的key,遇到相同查詢條件,數(shù)據(jù)可以直接反饋之前的查詢結(jié)果,而不需要再次去二級節(jié)點查詢服務(wù)處查詢。
③并發(fā)性。
對于批量的查詢,可以支持高并發(fā),充分利用CPU資源,快速反饋結(jié)果。多線程、多進程、分布式的實現(xiàn)方式是解決該問題的常用有效方法。例如:在此實例中,正對批量查詢會創(chuàng)建多個線程,同時執(zhí)行查詢?nèi)蝿?wù)。查詢服務(wù)結(jié)點部分ServerCenter_Content中運用SocketServer類,可以很好地處理并發(fā)的連接請求。
④可擴展性。
在設(shè)計整體系統(tǒng)時,要考慮到后續(xù)數(shù)據(jù)可能快速增加后帶來的查詢壓力問題。在系統(tǒng)架構(gòu)設(shè)計初期,需要充分調(diào)研需求,仔細(xì)分析業(yè)務(wù),做好層次模塊劃分、分層設(shè)計。當(dāng)數(shù)據(jù)量增加時,不用調(diào)整軟件架構(gòu),僅增加服務(wù)器設(shè)備就可以解決數(shù)據(jù)量大的問題和性能瓶頸。
⑤接口通信設(shè)計。
對于接口通信設(shè)計,在滿足數(shù)據(jù)傳輸要求的同時要盡量簡單,從而降低與其他業(yè)務(wù)聯(lián)合開發(fā)的耦合性。例如:該系統(tǒng)在前后端通信接口部分,主要應(yīng)用RabbitMQ消息隊列,傳輸前后端查詢條件和結(jié)果。這樣就不用單獨開發(fā)通信接口。復(fù)用開源成熟的通信接口,可以讓前后端的開發(fā)專注于業(yè)務(wù)。在后端內(nèi)部數(shù)據(jù)通信,應(yīng)用了SocketServer。該模塊對Socket類作了更好的封裝,增加了并發(fā)處理和異步等機制,簡化了通信編碼開發(fā)[11]。
數(shù)據(jù)來源是各地實時上傳的數(shù)據(jù)文件,接收程序會按照日期時間目錄分布存儲。如:2019-09-08 10∶22∶15接收的數(shù)據(jù)文件是171.125.3.157.log,將存儲在171.125.3.157服務(wù)器的/datastorage/20190908/10/22目錄下。
本文設(shè)計的AgentServer查詢代理類如表1所示。
表1 AgentServer查詢代理類
RabbitMQ消息請求接口內(nèi)容為:
json_info = {"mayjorType":"",#主模塊類型
"taskCount":"1",#批量任務(wù)數(shù)
"commitTime":"now",#批量任務(wù)提交時間
"tasks":{"taskName":"QueryAgent",#任務(wù)名稱
"createTime":"NOW",#任務(wù)創(chuàng)建時間
"taskID":"2",#任務(wù)ID(唯一)預(yù)留字段
"subType":"Query",固定Query
"detail":{}
}
}
RabbitMQ消息響應(yīng)接口內(nèi)容為:
message = {
′resType′:′response′,
′result′:[
{ ′code′:1,
′message′:′successful′,
′mayjorType′:′l′,
′subType′:′QueryAgent′,
′taskName′:′Query′,
′taskID′:′1′,
′resTime′:‘2019-05-06 14:18:14’,
′detail′:{ ′redisKey′:′′,′Result′:[]}
}
]
}
按照以上系統(tǒng)架構(gòu)設(shè)計軟件,編碼開發(fā)完成后,需要對整個軟件需求的功能進行部署測試。建議至少準(zhǔn)備2臺linux服務(wù)器:1臺部署QueryAgent 查詢代理機,1臺部署ServiceCenter_content程序查詢節(jié)點機,待查詢的原始數(shù)據(jù)按照以上存儲規(guī)則,存放在查詢節(jié)點機上。部署測試主要包含4個部分:①查詢結(jié)果準(zhǔn)確測試;②緩存機制加速效果測試;③并發(fā)查詢測試;④系統(tǒng)快速可擴展性測試。
查詢結(jié)果準(zhǔn)確率測試是本系統(tǒng)軟件設(shè)計的基本功能要求。緩存機制加速效果測試,是為了檢驗提高的查詢效率。針對歷史查詢可以快速反饋結(jié)果的測試,是系統(tǒng)用戶體驗的重要保證。并發(fā)查詢測試是指系統(tǒng)中同時有多個用戶批量查詢數(shù)據(jù)后,能及時、準(zhǔn)確反饋查詢結(jié)果的測試,是系統(tǒng)可靠性、健壯性的重要體現(xiàn)。系統(tǒng)快速可擴展性測試,在系統(tǒng)中的增加ServiceCenter_content查詢節(jié)點機,在不修改系統(tǒng)架構(gòu)和程序代碼的基礎(chǔ)上就可以滿足增大的基礎(chǔ)數(shù)據(jù)量查詢需求,且性能幾乎不受影響。
在信息大爆炸的時代,人們的工作和生活正在被大數(shù)據(jù)影響和改變。用戶如何在海量的數(shù)據(jù)中查詢到想要的信息變成一個尤為迫切的需求[12]。本次基于RabbitMQ和SocketServer的分布式查詢系統(tǒng)設(shè)計,為解決數(shù)據(jù)的查詢提供了很好的解決思路。該分布式查詢系統(tǒng)的設(shè)計和實現(xiàn),通過詳細(xì)的需求調(diào)研、分析數(shù)據(jù)、設(shè)計開發(fā)、部署測試,很好地滿足了用戶對原始數(shù)據(jù)追溯查詢的需求。此次軟件架構(gòu)的設(shè)計和開發(fā),為后續(xù)要解決查詢原始數(shù)據(jù)問題提供了實例。后續(xù)的設(shè)計和開發(fā)者,可以根據(jù)實際需求,參考以上設(shè)計和分析問題方法,解決實際問題。