蒲鳳平, 陳建政
(西南交通大學牽引動力國家重點實驗室, 成都 610031)
近年來,隨著互聯(lián)網(wǎng)的飛速發(fā)展,大型的分布式系統(tǒng)得到了前所未有的發(fā)展?!霸朴嬎恪保琒OA等的出現(xiàn)成為分布式系統(tǒng)發(fā)展過程中的重要里程碑[1]。在一個分布式系統(tǒng)中,一組獨立的計算機展現(xiàn)給用戶的是一個統(tǒng)一的整體,就好象是一個系統(tǒng)似的。通常,對用戶來說,分布式系統(tǒng)只有一個模型或范型。在操作系統(tǒng)之上有一層軟件中間件負責實現(xiàn)這個模型[2]。消息隊列中間件ZeroMQ[3]在兩年前推出,它具有很多方便分布式系統(tǒng)架構(gòu)的特點,可支持任意大的應(yīng)用程序。ZeroMQ不是簡單的點對點交互,相反,它定義了分布式系統(tǒng)的全局拓撲。ZeroMQ應(yīng)用程序沒有鎖,可并行運行。此外,它可在多個線程、內(nèi)核和主機盒之間彈性伸縮。ZeroMQ現(xiàn)在還在不斷更新中,但因它比同類產(chǎn)品有很多優(yōu)勢,逐漸被人們認識,得到很多好評。
ZeroMQ將網(wǎng)絡(luò)異常、異步、緩沖區(qū)、多線程等都封裝起來了,并且,ZeroMQ以消息為單位進行收發(fā),這樣省卻了很多代碼;ZeroMQ的API(Application Program Interface 應(yīng)用程序接口)很少,上手容易。ZeroMQ的消息格式如圖1[5]所示。
ZeroMQ以統(tǒng)一接口支持多種底層通信方式:線程間通信,進程間通信,跨主機通信。比如,如果要把多進程軟件用跨主機的環(huán)境中,只需要將通信協(xié)議由“ipc://xxx”改為”tcp://*.*.*.*.*:****”即可,而不需要改動其余代碼[6]。
圖1 消息格式
ZeroMQ支持4類通訊模式:請求回應(yīng)模式、發(fā)布訂閱模式、管道模式以及信號模式,其中,前3種模式使用較多,信號模式使用較少,主要是用來支持傳統(tǒng)的TCP socket模型。用這4種模式不僅可以實現(xiàn)傳統(tǒng)的一對一的通訊,還能實現(xiàn)一對多,甚至多對多的通訊。
ZeroMQ有超過20種以上的開發(fā)語言綁定,諸如C、C++、Java、.NET、Python等,支持絕大多數(shù)的操作系統(tǒng),例如Linux, Windows,OS X,如果開發(fā)的分布式系統(tǒng)比較復雜,常常不會只是一種語言或者一種平臺,ZeroMQ跨語言、跨平臺的特性就顯得很重要了。
1)RabbitMQ: 采用Erlang開發(fā)的,支持完善AMQP(Advanced Message Queuing Protocol,高級消息隊列協(xié)議);支持消息持久化和崩潰恢復,應(yīng)用程序在重新啟動之后消息不會丟失。它通過代理的模式實現(xiàn)分布式系統(tǒng),這種模式使系統(tǒng)的規(guī)模伸縮性會比較差,并且會降低系統(tǒng)效率,因為中央節(jié)點增加了延遲也讓消息的封裝更多[7]。
2)ActiveMQ: 支持STOMP(流文本定向消息協(xié),Streaming Text Orientated Message Protocol),有很長的使用歷史,并且被廣泛使用。容易實現(xiàn)很多高級的技術(shù),但是常常是以它的性能為代價,這對消息傳輸來說是一個很嚴重的問題。
3)ZeroMQ也支持高級消息隊列協(xié)議(AMQP),是很輕量級的消息隊列,沒有消息服務(wù)器來存儲和轉(zhuǎn)發(fā)消息,把側(cè)重點放在點對點的消息傳輸上。ZeroMQ剛推出不久,還不是很成熟,不支持消息持久化及崩潰恢復,且穩(wěn)定度較差。
由于ZeroMQ是用C/C++開發(fā),并且ZeroMQ協(xié)議格式定義得很簡單,所以它的性能遠遠高于其他消息隊列軟件。各種消息隊列性能測評結(jié)果如圖2[8]所示。
圖2 各種消息隊列性能測評結(jié)果
從這幾種同類軟件的比較得知,它們各有優(yōu)缺點,我們應(yīng)該根據(jù)自己的項目情況,選擇合適的,揚長避短。本課題主要是要設(shè)計一個高效的分布式網(wǎng)絡(luò),對穩(wěn)定性要求不是太高,無疑,ZeroMQ是最佳選擇。
分布式系統(tǒng)由一個manager、N個客戶機和N個服務(wù)器組成,N可以是任意數(shù)量??蛻魴C和服務(wù)器都稱作子系統(tǒng)。每個子系統(tǒng)可以隨時加入或退出系統(tǒng),并且子系統(tǒng)的加入或退出不影響其他子系統(tǒng)。在傳統(tǒng)的通訊系統(tǒng)中,客戶機向服務(wù)器發(fā)出的請求,以及服務(wù)器做出的回應(yīng)都會經(jīng)manager中轉(zhuǎn),這樣,隨著客戶機和服務(wù)器數(shù)量的增多,manager就會成為一個瓶頸。該系統(tǒng)摒棄了這種傳統(tǒng)模式,把manager的功能進行了分割,manager僅保留了目錄服務(wù)的功能。例如,應(yīng)用程序X開機后向manager注冊,讓manager知道它運行在機子Y上,應(yīng)用程序Z想發(fā)送一個消息給應(yīng)用程序X,那么它就向manager咨詢X的位置。當manager回應(yīng)應(yīng)用程序X在機子Y上以后,Z可以直接與Y創(chuàng)建連接,并直接和Y通訊,而不用經(jīng)過manager中轉(zhuǎn)。不僅各個子系統(tǒng)能與manager通信,任何客戶機與任何服務(wù)器也能相互通信。網(wǎng)絡(luò)拓撲結(jié)構(gòu)如圖3所示。
圖3 拓撲圖
ZeroMQ有現(xiàn)成的動態(tài)鏈接庫libzmq.lib,為了實現(xiàn)我們的分布式通信網(wǎng)絡(luò),需要調(diào)用動態(tài)鏈接庫中的API函數(shù)。Libzmq.lib中僅封裝了二十多個API函數(shù)。因為這些函數(shù)的某些參數(shù)的數(shù)據(jù)類型并非基本類型,并且如果直接調(diào)用這些函數(shù),必定會有很多代碼會被重復編寫。為了解決這兩個問題,對這些函數(shù)都重新進行了封裝,
2.2.1開發(fā)平臺
有人說真正的程序用C,聰明的人用Delphi。因為Delphi開發(fā)時間短,提供了許多個可供使用的組件,很方便設(shè)計人機交互界面,功能可與C相當。Delphi是采用面向?qū)ο蟮木幊陶Z言O(shè)bject Pascal,而ZeroMQ是利用C語言開發(fā)的,為此,首先將原有的C動態(tài)鏈接庫中的函數(shù)封裝成容易看懂的形式,然后再次封裝成動態(tài)鏈接庫,最后在Delphi下調(diào)用這些函數(shù),以實現(xiàn)需要的功能。
2.2.2 方案確定
1)manager對服務(wù)器的管理:manager作為目錄服務(wù)器,它要管理別的服務(wù)器,包括服務(wù)器是否在線,某服務(wù)器是提供什么服務(wù)的,服務(wù)器的綁定端口等。manager會為同一類型的服務(wù)器創(chuàng)建一個隊列,對服務(wù)器進行管理。為了不要讓服務(wù)器存在餓死的情況,manager利用最近最少使用算法為客戶機選擇服務(wù)器。為了知道服務(wù)器是否在線,manager與服務(wù)器之間使用心跳。即,在服務(wù)器向manager注冊后,在某個固定的時間段內(nèi)如果manager和服務(wù)器沒有收到來自對方的消息(包括心跳和連接請求等)則認為對方已下線。
對于客戶端和服務(wù)器的請求(包括連接請求,心跳,服務(wù)請求等),manager使用單一套接字進行處理。因為,與使用兩個套接字分別處理客戶端和服務(wù)器請求相比,manager更方便管理。
2)通訊模式的選擇:ZeroMQ主要提供了請求回應(yīng)、發(fā)布訂閱、管道和信號4種通訊模式。其中,第4種用得比較少,主要是用來支持傳統(tǒng)的 TCP socket 模型。ZeroMQ的套接字必須配對使用,對于請求回應(yīng)模式有效的套接字對有:REQ and REP、 REQ and XREP 、XREQ and REP、XREQ and XREP、XREQ and XREQ、 XREP and XREP,這4種套接都既能發(fā)送消息,又能接收消息,但是REQ和REP要求收發(fā)消息,而XREQ和XREP可以異步收發(fā)消息;發(fā)布訂閱有效的套接字對是PUB and SUB,其中,PUB只能發(fā)送消息,SUB只能接收消息;管道模式的有效套接字對是PUSH and PULL,其中PUSH只能發(fā)送消息,PULL只能接收消息;信號模式的有效套接字對是PAIR and PAIR,這種模式主要用于進程內(nèi)通信。
manager要能夠區(qū)分連接到它的不同的子系統(tǒng),才能將回應(yīng)或者心跳路由過去,所以manager端的套接字必須有路由能力,只有XREP有這個功能,所以manager使用套接字XREP實現(xiàn)通訊。
服務(wù)器與manager之間的心跳機制本身不是同步的,所以不能使用REQ或者REP,所以方案為服務(wù)器與manager的連接選擇套接字XREQ。而服務(wù)器與客戶機的通訊同樣不是單向和同步的,并且有可能有多個客戶機連接到同一個服務(wù)器,所以,此時的服務(wù)器也要有路由功能,即,只能利用套接字XREP實現(xiàn)。
與manager的通信時,客戶機是發(fā)送一個消息然后接收一個回應(yīng),是同步的雙向通信,所以REQ,XREQ,XREP都可以,但是為了后續(xù)對消息的封裝容易格式統(tǒng)一,選擇XREQ實現(xiàn)。而與服務(wù)器的通訊是異步的雙向通訊,所以同樣選擇XREQ套接字來實現(xiàn)。
3)消息的封裝格式
由于manager使用單一的套接字處理客戶機和服務(wù)器發(fā)來的所有請求,所以這些消息除了包含消息內(nèi)容還必須封裝進消息類型。
客戶機發(fā)送給manager的消息封裝格式為:
Frame1:”Client”(代表客戶機)
Frame2:Service name(請求的服務(wù)類型)
Manager發(fā)送給客戶機的回應(yīng)消息封裝格式為:
Frame1:”Client”(代表客戶機)
Frame2:Service name(請求的服務(wù)類型)
Frame3:Server’s port(服務(wù)器端口號)
服務(wù)器發(fā)送給manager的注冊信息:
Frame1:”Worker”(代表服務(wù)器)
Frame2:”READY”(表示服務(wù)器已準備好)
Fream3:Service name(提供的服務(wù)類型)
服務(wù)器與manager間發(fā)送的心跳:
Frame1:”Worker”(代表服務(wù)器)
Frame2:“HEARTBEAT”(心跳)
manager感知整個系統(tǒng)的拓撲。子系統(tǒng)開機后,首先連接上manager,接著發(fā)送一個消息給manager(客戶機發(fā)送請求的服務(wù)類型;服務(wù)器發(fā)送自身的名稱、IP地址及提供的服務(wù)類型)。manager根據(jù)消息類型判斷是來自客戶機還是服務(wù)器,如果來自服務(wù)器,并且控制命令是”READY”,則根據(jù)service name信息判斷是否已經(jīng)存在這項服務(wù)的隊列,如果不存在則創(chuàng)建一個新的隊列,如果存在則把此服務(wù)器信息添加到這個隊列最后;如果控制命令是“HEATER”,則重置此服務(wù)器的心跳截止時間。若來自客戶機,則查找是否存在客戶機請求的服務(wù)類型對應(yīng)的服務(wù)器,若存在則從服務(wù)隊列中取出對列首的服務(wù)器的端口信息發(fā)送給客戶機,并將該服務(wù)器放到隊列末尾;否則回復服務(wù)器不存在的消息,如“sorry!”。manager同時利用心跳機制監(jiān)測服務(wù)器的在線信息,如果發(fā)現(xiàn)服務(wù)器下線,則從服務(wù)隊列中將該服務(wù)器刪除。程序流程的粗略框架如圖4所示。
圖4 manager處理流程圖
服務(wù)器向manager注冊后,等待客戶機連接,直接與客戶機通訊,并定時向manager發(fā)送heartbeat信息。服務(wù)器的程序流程粗略框架如圖5所示。
客戶機向服務(wù)器請求前,首先連接到manager,向manager咨詢是否有提供某項服務(wù)的服務(wù)器存在,如果manager返回服務(wù)器的端口號,則客戶機連接到服務(wù)器,直接向服務(wù)器 請求數(shù)據(jù);如果manager返回的是“sorry!”,則客戶機等待一段時間再重新連接??蛻魴C的程序流程的粗略框架如圖6所示。
圖6 客戶機處理流程圖
為了測試ZeroMQ的性能,在兩臺電腦之間發(fā)送數(shù)據(jù)10000000條消息,接收只用了不到0.2 μs。說以,實驗證實了ZeroMQ的高效性。測試結(jié)果如圖7所示。
圖7 測試結(jié)果
這個系統(tǒng)已經(jīng)用于輪軌檢測的試驗中。由于,檢測的時間長,并且檢測點多等特點,短時間采集到大量數(shù)據(jù),采集卡的存儲空間遠遠不夠,所以,如何及時把數(shù)據(jù)轉(zhuǎn)運走就是一個很關(guān)鍵的問題?;赯eroMQ通訊系統(tǒng)的交互面向消息,并使用消息分批發(fā)送,大大提高了傳輸效率,從而有效地解決了數(shù)據(jù)存儲難的問題。
本系統(tǒng)是一個基于ZeroMQ小型的分布式系統(tǒng)。ZeroMQ的消息傳送機制大大提高了傳輸效率,并且它的接口函數(shù)簡單容易上手。系統(tǒng)中使用的平臺是Delphi2007,它提供了許多個可供使用的構(gòu)件,方便開發(fā)人機交互界面。實踐證明本系統(tǒng)能實現(xiàn)高效的數(shù)據(jù)傳輸。然而,本系統(tǒng)還存在一個缺點:如果manager出現(xiàn)問題,整個系統(tǒng)就會崩潰掉。這個問題可以根據(jù)實際情況通過增加一個備用manager來解決。ZeroMQ剛推出不久,國內(nèi)外的應(yīng)用還比較少,主要集中在web應(yīng)用上,但因其較同類軟件具有顯著優(yōu)勢,越來越受到大家的青睞。同時,ZeroMQ還存在不支持消息持久化和崩潰恢復等問題。ZeroMQ還在不斷完善中,希望這些問題在以后都能得到很好的解決。
[1]溫情月朗.分布式系統(tǒng)介紹[EB/OL].http://qa.taobao.com/?p=3527,2009.
[2]SOSO百科.分布式系統(tǒng)[EB/OL].http://baike.soso.com/v5697460.htm.
[4]program_think.開源點評:ZeroMQ簡介[EB/OL].http://blog.csdn.net/program_think/article/details/6687076,2011.
[5]鄒永斌.Introduction to Message Oriented Middleware[EB/OL].http://wenku.baidu.com/view/3ba1a73710661ed9ad51f394.html,2011.
[6]Dccmx.史上最快消息內(nèi)核—ZeroMQ[EB/OL].http://itindex.net/detail/4067-%E6%B6%88%E6%81%AF-%E5%86%85%E6%A0%B8-zeromq,2011.
[7]Julien.ActiveMQ or RabbitMQ or ZeroMQ or ActiveMQ[EB/OL].http://stackoverflow.com/questions/731233/activemq-or-rabbitmq-orzeromq-or,2009.
[8]SZSM.測試比較:消息隊列軟件產(chǎn)品大比拼