王鈺, 葉徳建
(1. 復(fù)旦大學(xué) 軟件學(xué)院, 上海 201203; 2. 網(wǎng)絡(luò)信息安全審計(jì)與監(jiān)控教育部工程研究中心, 上海 201203)
基于商用多媒體云平臺(tái)的終端推送服務(wù)設(shè)計(jì)
王鈺1, 葉徳建2
(1. 復(fù)旦大學(xué) 軟件學(xué)院, 上海 201203; 2. 網(wǎng)絡(luò)信息安全審計(jì)與監(jiān)控教育部工程研究中心, 上海 201203)
從商用多媒體云平臺(tái)的業(yè)務(wù)需求出發(fā),設(shè)計(jì)了一種終端推送服務(wù)。將推送流水的存儲(chǔ)、推送消息的發(fā)送和推送消息的確認(rèn)分成3個(gè)不同的模塊分別完成,實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)推送,同時(shí)上層服務(wù)管理終端分組,保證了推送消息的可靠到達(dá)。實(shí)驗(yàn)證明,該推送服務(wù)的內(nèi)存占用穩(wěn)定,推送效率高,吞吐量高,能滿足商用多媒體云平臺(tái)的點(diǎn)對(duì)點(diǎn)分組推送功能。
終端推送; 消息可靠到達(dá); 點(diǎn)對(duì)點(diǎn)推送
互聯(lián)網(wǎng)時(shí)代,消息推送服務(wù)[1]在我們身邊得到了廣泛的應(yīng)用。推送服務(wù)指的是客戶端與服務(wù)器之間保持長(zhǎng)連接心跳,服務(wù)器有新消息需要發(fā)送時(shí),主動(dòng)向客戶端推送信息,相比客戶端的定時(shí)請(qǐng)求服務(wù),這種方式減少了交互次數(shù),提高了推送效率。
近年來(lái),在酒店VOD、校園OTT-TV、戶外廣告等行業(yè)中,以視頻業(yè)務(wù)和信息發(fā)布業(yè)務(wù)為主的商用多媒體系統(tǒng)的應(yīng)用越來(lái)越廣泛。隨著云計(jì)算技術(shù)的發(fā)展,基于云平臺(tái)構(gòu)建的商用多媒體系統(tǒng)成為了主流。
終端推送服務(wù)是商用多媒體云平臺(tái)[2]面向終端的重要服務(wù),信息發(fā)布系統(tǒng)、OTT系統(tǒng)等均依靠該服務(wù)將廣告、節(jié)目單等信息推送到指定終端設(shè)備。在云平臺(tái)的終端推送[3]方面,運(yùn)營(yíng)商往往需要向不同的終端推送不同的內(nèi)容,例如商場(chǎng)的信息發(fā)布系統(tǒng)可在多個(gè)屏幕展示不同的產(chǎn)品介紹,推送內(nèi)容大多是運(yùn)營(yíng)商需要發(fā)布的重要信息,不允許信息丟失。
文獻(xiàn)[1]中采用Netty框架開(kāi)發(fā),對(duì)傳統(tǒng)網(wǎng)絡(luò)服務(wù)器采用的阻塞IO開(kāi)發(fā)引起的大量客戶情況下推送服務(wù)中CPU利用效率低下的問(wèn)題,但是并沒(méi)有解決推送服務(wù)中信息丟失的問(wèn)題。文獻(xiàn)[4]是多媒體終端推送業(yè)務(wù)功能的研究,但未能解決商用多媒體云平臺(tái)推送服務(wù)的點(diǎn)對(duì)點(diǎn)推送需求。
目前可用的推送技術(shù)主要基于MQTT[5]或XMPP協(xié)議,二者均使用長(zhǎng)連接實(shí)現(xiàn)推送。
MQTT協(xié)議,是一個(gè)輕量級(jí)的基于“發(fā)布/訂閱”模式的消息傳輸協(xié)議,協(xié)議開(kāi)放,擴(kuò)展性強(qiáng),提供一對(duì)多的消息發(fā)布,適用于帶寬比較低或者不穩(wěn)定的網(wǎng)絡(luò)環(huán)境。
XMPP[6]協(xié)議,是用于實(shí)時(shí)通信的協(xié)議,通信報(bào)文格式基于XML,實(shí)時(shí)通信技術(shù)和推送的底層技術(shù)是一樣的。該協(xié)議可實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)推送,但其基于XML的通信報(bào)文數(shù)據(jù)傳輸量較大,為實(shí)時(shí)通信而設(shè)計(jì)的XMPP對(duì)于推送冗余功能過(guò)多。在商用多媒體系統(tǒng)中,各種云服務(wù)之間的業(yè)務(wù)數(shù)據(jù)需要互相關(guān)聯(lián),而XMPP服務(wù)器的集群部署模式下只支持單一數(shù)據(jù)庫(kù),無(wú)法分庫(kù)分表,數(shù)據(jù)相對(duì)封閉。在XMPP協(xié)議中,各服務(wù)器不存儲(chǔ)在線消息的發(fā)送流水,當(dāng)在線功能由于異常(如服務(wù)器負(fù)載過(guò)高或突然故障)導(dǎo)致發(fā)送失敗時(shí),缺乏容錯(cuò)機(jī)制,無(wú)法保證消息的可靠到達(dá)。
綜上,MQTT協(xié)議需要為每個(gè)終端分配唯一的Topic來(lái)實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)推送,管理不便,XMPP協(xié)議可用于點(diǎn)對(duì)點(diǎn)推送,但協(xié)議內(nèi)容冗余,傳輸?shù)臄?shù)據(jù)量大,數(shù)據(jù)模型相對(duì)封閉,消息容易丟失。所以,它們均不適用于商用多媒體云平臺(tái)的終端推送服務(wù)。商用多媒體云平臺(tái)終端推送服務(wù)的需求是:實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)推送,終端推送服務(wù)本身不管理終端分組,上層服務(wù)基于點(diǎn)對(duì)點(diǎn)推送可以方便實(shí)現(xiàn)分組管理及分組發(fā)送;保證推送消息至少成功到達(dá)終端一次。基于此需求,我們針對(duì)該商用多媒體云平臺(tái)設(shè)計(jì)一個(gè)定制的推送協(xié)議,基于Exchange ActiveSync[7]協(xié)議改進(jìn)。
1.1 可靠消息隊(duì)列RocketMQ
RocketMQ是一款分布式消息中間件,基于消息隊(duì)列模式,持久化存儲(chǔ)隊(duì)列,消息順序可靠,實(shí)時(shí)消息訂閱,具有高可靠、高性能、易擴(kuò)展的特點(diǎn)。
RocketMQ分為NameServer和Broker兩部分,NameServer存儲(chǔ)了消息隊(duì)列中所有的配置信息,Broker則負(fù)責(zé)消息的存儲(chǔ)轉(zhuǎn)發(fā)。RocketMQ使用“Topic/Queue”的模型,一個(gè)Topic是多個(gè)隊(duì)列的集合,平均部署在多個(gè)Broker上,增加Broker數(shù)量就可以直接提高吞吐量,易擴(kuò)展的同時(shí)實(shí)現(xiàn)負(fù)載均衡。每個(gè)Broker分為Master節(jié)點(diǎn)和Slave節(jié)點(diǎn),Master負(fù)責(zé)接收、存儲(chǔ)和投遞消息,Slave則負(fù)責(zé)進(jìn)行冗余備份,從而提升可靠性。生產(chǎn)者和Broker之間保持心跳連接,從而在某個(gè)Broker故障時(shí),自動(dòng)選擇其他Broker發(fā)送消息,消費(fèi)者從該Broker的Slave節(jié)點(diǎn)繼續(xù)接收消息,提高可用性。RocketMQ采用高并發(fā)的方式提高吞吐量,消息消費(fèi)失敗不會(huì)阻塞后續(xù)消息的投遞,性能很高但不保證消息嚴(yán)格有序。
1.2 Java的Netty框架
Netty[8]是基于Java非阻塞IO的網(wǎng)絡(luò)編程框架,該框架將非阻塞IO與IO復(fù)用結(jié)合起來(lái),具有較高的網(wǎng)絡(luò)傳輸效率,同時(shí)還提供了基于事件響應(yīng)和回調(diào)方法的異步編程模型,是目前主流的Java網(wǎng)絡(luò)編程框架。使用Netty框架可以極大簡(jiǎn)化選擇器監(jiān)聽(tīng)、連接創(chuàng)建、心跳處理、連接異常處理等各個(gè)環(huán)節(jié)的開(kāi)發(fā)工作。
1.3 Memcache緩存
Memcache[9]是開(kāi)源的基于一致哈希的分布式鍵值系統(tǒng),數(shù)據(jù)全部存儲(chǔ)于內(nèi)存中,常用作系統(tǒng)緩存,讀寫(xiě)速度快,當(dāng)節(jié)點(diǎn)故障時(shí),相鄰節(jié)點(diǎn)的替代提高了其可用性。
2.1 架構(gòu)設(shè)計(jì)
終端推送服務(wù)要保證推送消息可靠到達(dá)終端,需要在異常情況下對(duì)丟失的推送消息進(jìn)行記錄并重試,因此終端推送需要存儲(chǔ)所有的推送發(fā)送流水,終端在收到推送消息之后要反饋確認(rèn),從而確定丟失的推送。但是若在發(fā)送推送過(guò)程中存儲(chǔ)發(fā)送流水,則會(huì)降低終端推送的吞吐量。本文在終端推送服務(wù)的設(shè)計(jì)中,將推送流水的存儲(chǔ)、推送消息的發(fā)送和推送消息的確認(rèn)分成3個(gè)不同的模塊分別完成,從而將3部分操作解耦。在3個(gè)模塊中,可以調(diào)節(jié)部署的服務(wù)器數(shù)量來(lái)維持系統(tǒng)整體吞吐量的平衡。
終端推送服務(wù)的整體架構(gòu),如圖1所示。
整體架構(gòu)分為3部分:
門(mén)戶模塊(Facade模塊):接收來(lái)自其他服務(wù)的推送請(qǐng)求,通知相應(yīng)的broker模塊發(fā)送推送消息,保存和維護(hù)終端推送服務(wù)的狀態(tài)(終端與Broker之間的映射關(guān)系、終端在線狀態(tài)等),保存推送消息的發(fā)送流水;
圖1 終端推送服務(wù)的整體架構(gòu)
推送模塊(Broker模塊):接收來(lái)自Facade模塊的請(qǐng)求,將推送消息發(fā)送給指定終端;
消息確認(rèn)模塊:接收來(lái)自終端的確認(rèn)消息,更新推送消息發(fā)送流水的狀態(tài);
3個(gè)模塊的職責(zé)及維護(hù)的數(shù)據(jù),如表1所示。
表1 推送服務(wù)各模塊的職責(zé)
其中,每臺(tái)Broker服務(wù)器都存儲(chǔ)了終端MAC地址和終端Channel連接之間的映射關(guān)系,這部分?jǐn)?shù)據(jù)只存儲(chǔ)在內(nèi)存中。Facade模塊在終端上下線時(shí)接收終端發(fā)來(lái)的RocketMQ消息,之后對(duì)終端與Broker模塊中各服務(wù)器的映射關(guān)系進(jìn)行修改和保存。此處采用異步的RocketMQ消息,其他云服務(wù)也可以訂閱終端上下線的該消息,例如:云平臺(tái)的運(yùn)營(yíng)服務(wù)可以通過(guò)訂閱各個(gè)終端的上下線消息來(lái)計(jì)算終端的活躍時(shí)間。Facade模塊還負(fù)責(zé)接收分布式定時(shí)任務(wù)的通知,查詢發(fā)送失敗的推送消息流水,通過(guò)不斷重試進(jìn)行異步補(bǔ)償,直至推送消息被確認(rèn)。
2.2 協(xié)議設(shè)計(jì)
推送協(xié)議,如表2所示。
該推送協(xié)議設(shè)計(jì)十分精簡(jiǎn),共有4種指令:login指令是終端在發(fā)起長(zhǎng)連接時(shí),發(fā)送給推送服務(wù)的第一條指令,攜帶終端在開(kāi)機(jī)認(rèn)證過(guò)程中生成的token等信息,推送服務(wù)可以調(diào)用終端的管理認(rèn)證服務(wù)驗(yàn)證合法性,如果認(rèn)證失敗或者連接建立后未發(fā)送login指令,則推送服務(wù)關(guān)閉連接,認(rèn)證成功則云平臺(tái)通過(guò)推送服務(wù)返回認(rèn)證結(jié)果給終端;heart指令用于維護(hù)終端和云平臺(tái)之間的推送服務(wù)的長(zhǎng)連接,如果任何一方在一定時(shí)間內(nèi)未收到心跳則主動(dòng)關(guān)閉連接,終端開(kāi)始重連;push指令是在長(zhǎng)連接中發(fā)送給終端的指令,執(zhí)行推送操作,該指令包含終端MAC地址、推送消息內(nèi)容體等;ack指令是終端在收到push指令之后回復(fù)給推送服務(wù)的確認(rèn)命令,推送服務(wù)在收到ack指令之后記錄相應(yīng)終端的push消息為到達(dá)狀態(tài)。
表2 推送協(xié)議
整體協(xié)議由長(zhǎng)連接和HTTP兩部分組成,通過(guò)長(zhǎng)連接來(lái)發(fā)送推送消息的內(nèi)容,通過(guò)HTTP來(lái)確認(rèn)推送消息的到達(dá)。這種設(shè)計(jì)極大地降低了長(zhǎng)連接管理方面的難度,管理長(zhǎng)連接的服務(wù)器不需要記錄推送消息是否到達(dá),提高了推送效率。對(duì)于未收到確認(rèn)的推送消息,由分布式定時(shí)任務(wù)異步補(bǔ)償不斷重試直到確認(rèn)為止。
2.3 終端、Broker模塊及Facade模塊之間的交互
Broker模塊使用Java的Netty框架實(shí)現(xiàn),Netty框架將網(wǎng)絡(luò)套接字封裝成Channel類型,后文將使用Channel表示非阻塞的Socket連接。
終端/二級(jí)服務(wù)器在上/下線時(shí)與Broker模塊之間的交互順序,如圖2所示。
圖2 終端與Broker模塊的交互
終端通過(guò)與Broker模塊的連接進(jìn)行登錄,完成登錄認(rèn)證的初始化階段。
終端與Broker模塊建立連接之后,先發(fā)送攜帶Token的login指令,Broker模塊收到指令后調(diào)用終端認(rèn)證服務(wù)檢測(cè)Token的合法性,并返回認(rèn)證結(jié)果,認(rèn)證成功則返回Token對(duì)應(yīng)終端的MAC地址。認(rèn)證通過(guò)后,broker模塊將終端MAC地址和Channel的映射關(guān)系保存在內(nèi)存中,之后broker模塊發(fā)送RocketMQ消息通知Facade終端上線,F(xiàn)acade模塊記錄并保存終端和Broker模塊服務(wù)器的映射,RocketMQ消息內(nèi)容為“[online]終端MAC地址+Broker模塊服務(wù)器IP+時(shí)間戳”。Broker模塊和終端之間始終保持心跳交互,一方超過(guò)指定時(shí)間未收到心跳包,broker模塊將主動(dòng)關(guān)閉終端對(duì)應(yīng)的Channel,如果Channel在認(rèn)證成功后被關(guān)閉,broker模塊會(huì)將MAC地址和Channel的映射關(guān)系中刪除對(duì)應(yīng)的數(shù)據(jù),并發(fā)送RocketMQ消息通知Facade該終端下線,該消息和上線時(shí)發(fā)送的內(nèi)容類似。
Facade與Broker模塊之間的交互,如圖3所示。
圖3 Facade模塊和Broker模塊的交互
Facade模塊同樣作為Broker模塊的客戶端進(jìn)行登錄認(rèn)證,與終端不同,F(xiàn)acade模塊登錄時(shí)使用特殊的Token——字符串facade,Broker模塊檢測(cè)到該Token之后,對(duì)登錄者的IP進(jìn)行驗(yàn)證,F(xiàn)acade模塊的IP地址應(yīng)為內(nèi)網(wǎng)IP,Broker模塊檢測(cè)出是內(nèi)網(wǎng)IP則返回登錄成功,否則返回登錄失敗。當(dāng)Facade模塊收到來(lái)自其他服務(wù)的推送調(diào)用請(qǐng)求時(shí),查找終端對(duì)應(yīng)的Broker模塊,發(fā)送push指令給對(duì)應(yīng)的Broker服務(wù)器,Broker模塊在終端MAC地址和Channel的映射關(guān)系中查找到對(duì)應(yīng)Channel并將push指令發(fā)送給終端。Facade模塊和Broker模塊之間也要維持心跳交互,如果二者之間的連接被關(guān)閉,F(xiàn)acade模塊將不斷重試連接直至成功。
2.4 Broker模塊
Broker模塊有幾個(gè)關(guān)鍵工作。在收到客戶端發(fā)來(lái)的報(bào)文時(shí),首先判斷發(fā)過(guò)來(lái)的指令是否為login指令,根據(jù)協(xié)議規(guī)定,客戶端建立連接之后,發(fā)送的第一條必須是login指令,因此對(duì)于非login指令,處理器將關(guān)閉channel。然后,檢測(cè)login指令的Token是否為字符串facade,從而區(qū)分客戶端類型為終端設(shè)備或Facade模塊的服務(wù)器。對(duì)于來(lái)自內(nèi)部的Facade模塊連接請(qǐng)求,通過(guò)客戶端IP地址是否為內(nèi)網(wǎng)進(jìn)行認(rèn)證,后對(duì)Channel做標(biāo)記。對(duì)于來(lái)自外部終端設(shè)備的連接請(qǐng)求,Broker模塊將調(diào)用終端認(rèn)證服務(wù)檢測(cè)該終端合法性,認(rèn)證通過(guò)后,發(fā)送RocketMQ消息通知Facade模塊終端上線,同時(shí)保存該MAC地址和Channel之間的映射關(guān)系,并注冊(cè)Channel關(guān)閉事件的回調(diào)方法。當(dāng)Channel被關(guān)閉時(shí),將該Channel和MAC地址的映射關(guān)系刪除并給Facade發(fā)送終端下線的RocketMQ消息,最后將Channel標(biāo)記為外部連接并記錄終端的MAC地址。以上的認(rèn)證操作只在連接新建立的時(shí)候執(zhí)行一次,之后通過(guò)這個(gè)Channel進(jìn)行后續(xù)操作時(shí),無(wú)需認(rèn)證操作,但是Broker與客戶端之間要維持心跳交互。
Broker模塊在收到push指令時(shí),檢查是否由Facade模塊發(fā)出和指令的正確性。然后Broker模塊根據(jù)該指令中的指定的終端MAC地址查找到對(duì)應(yīng)的Channel,將push指令從該Channel轉(zhuǎn)發(fā)出去,如果在轉(zhuǎn)發(fā)push指令的過(guò)程中發(fā)生任何異常,例如終端MAC地址對(duì)應(yīng)的Channel不存在,Broker模塊將簡(jiǎn)單地丟棄消息,后續(xù)由分布式定時(shí)任務(wù)進(jìn)行異步補(bǔ)償。
2.5 Facade模塊
Broker模塊的輕量型設(shè)計(jì)使得我們的推送系統(tǒng)具有較高的性能,而Facade模塊需要處理較為重量級(jí)的工作:1) 維護(hù)終端與Broker模塊服務(wù)器之間的映射關(guān)系;2) 存儲(chǔ)推送消息發(fā)送流水;3) 執(zhí)行分布式定時(shí)任務(wù),對(duì)發(fā)送失敗的push消息進(jìn)行異步補(bǔ)償。
Facade模塊的數(shù)據(jù)庫(kù)需要保存終端與Broker模塊服務(wù)器之間的映射,同時(shí)存儲(chǔ)推送消息的發(fā)送流水,數(shù)據(jù)庫(kù)模型,如圖4所示。
圖4 Facade模塊的數(shù)據(jù)庫(kù)模型
其中MAC_BROKER表記錄了終端MAC地址與Broker模塊服務(wù)器之間的映射關(guān)系,終端MAC地址具有唯一性約束。Facade模塊在發(fā)送push消息時(shí),為了查找終端對(duì)應(yīng)的Broker模塊服務(wù)器,需要在MAC_BROKER表中進(jìn)行大量的查詢操作。為了提高查詢效率,在Memcache集群中為該表建立Key-Value查詢緩存,Key為終端MAC地址。每次查詢先從緩存查詢,查詢不到再?gòu)臄?shù)據(jù)庫(kù)查詢,并將結(jié)果寫(xiě)入緩存;每次更新數(shù)據(jù)庫(kù)時(shí)對(duì)緩存進(jìn)行更新,保持?jǐn)?shù)據(jù)一致性。
MAC_MSG表記錄了Facade模塊對(duì)push消息的發(fā)送流水,終端MAC地址和Push消息ID聯(lián)合組成唯一性約束,表中STATUS字段表示push流水狀態(tài):INIT表示未收到回復(fù),ACK表示已收到回復(fù)。MSG表則為push消息的歷史記錄表。一定時(shí)間后通過(guò)定時(shí)任務(wù)將這段時(shí)間的MAC_MSG數(shù)據(jù)表遷移到歷史記錄表中,同時(shí)檢查push流水狀態(tài),記錄并報(bào)告未收到回復(fù)的流水,但是將放棄重新推送該push消息。
外圍系統(tǒng)在調(diào)用終端推送服務(wù)時(shí),需要在Facade模塊注冊(cè)push消息并獲得ID,然后向Facade模塊發(fā)送RocketMQ消息,內(nèi)容包括push消息ID和終端MAC地址列表,在列表數(shù)量過(guò)多的情況下將拆分成多個(gè)RocketMQ消息發(fā)送給推送服務(wù)。
Facade模塊的推送服務(wù)流程,如圖5所示。
圖5 Facade模塊的流程圖
Facade模塊收到推送請(qǐng)求后,將push消息發(fā)送流水插入到數(shù)據(jù)庫(kù)MAC_MSG表中,同時(shí)由另一個(gè)消費(fèi)者將發(fā)送流水向業(yè)務(wù)線程池提交push任務(wù),由業(yè)務(wù)線程池異步執(zhí)行push消息推送。RocketMQ消息中如果有push消息流水未插入成功,則返回失敗,RocketMQ將重新投遞失敗的消息,MAC_MSG表的唯一索引可以防止重復(fù)插入。業(yè)務(wù)線程池在MAC_BROKER表中查找當(dāng)前push流水需要的Broker服務(wù)器IP,并通過(guò)Broker模塊的客戶端將push消息發(fā)送出去。
當(dāng)Facade模塊收到終端上下線的RocketMQ消息時(shí),要更新MAC_BROKER表和Memcache緩存中的MAC地址和服務(wù)器IP的映射關(guān)系。終端上線時(shí),將表中Broker字段更新為真實(shí)IP,下線時(shí)更新為OFFLINE。并同步更新Memchache緩存,比較RocketMQ消息中的時(shí)間戳和數(shù)據(jù)庫(kù)記錄的時(shí)間戳大小,防止更新過(guò)期的RocketMQ消息。終端上線時(shí),F(xiàn)acade模塊需要查詢?cè)摻K端是否有未確認(rèn)的push消息流水記錄,有則需要發(fā)送對(duì)應(yīng)push消息到業(yè)務(wù)線程池。
由于Facade模塊的兩個(gè)消費(fèi)者異步處理RocketMQ消息,一個(gè)負(fù)責(zé)落庫(kù)發(fā)送流水,一個(gè)負(fù)責(zé)封裝并提交push任務(wù),若出現(xiàn)一條流水在落庫(kù)之前已經(jīng)完成了推送操作,則直接在數(shù)據(jù)庫(kù)中插入該流水,并將該流水狀態(tài)記錄為ack。同一條流水多次發(fā)送的情況由客戶端自行處理。
對(duì)于終端未成功收到push消息的情況,通過(guò)分布式定時(shí)任務(wù)進(jìn)行異步補(bǔ)償,執(zhí)行頻率為每分鐘一次。Facade模塊將查詢MAC_MSG表中所有需要重發(fā)的push消息流水記錄。當(dāng)流水狀態(tài)為INIT,終端處于在線狀態(tài),流水的更新時(shí)間超過(guò)一分鐘這三個(gè)條件同時(shí)滿足時(shí),從MSG表中將流水的push內(nèi)容體封裝,并和push流水組裝成pushTask提交到Facade模塊的業(yè)務(wù)線程池,從而將push消息發(fā)送到終端。
商用多媒體平臺(tái)終端推送服務(wù)為了達(dá)到點(diǎn)對(duì)點(diǎn)推送、分組管理發(fā)送、準(zhǔn)確到達(dá)等需求,定制設(shè)計(jì)成推送流水的存儲(chǔ)、推送消息的發(fā)送和推送消息的確認(rèn)三個(gè)模塊,以下是該終端推送服務(wù)的相關(guān)測(cè)試。
3.1 Broker模塊的內(nèi)存占用和推送效率測(cè)試
由于Broker模塊所在的服務(wù)器會(huì)與大量的終端建立長(zhǎng)連接,因此對(duì)Broker模塊內(nèi)存占用和連接數(shù)之間的關(guān)系進(jìn)行了測(cè)試。在Clear商用多媒體云平臺(tái)環(huán)境下,用單臺(tái)虛擬機(jī)搭建了Broker模塊,用軟件模擬支持自定義推送協(xié)議的終端,記錄Broker服務(wù)器的內(nèi)存隨著終端增加的變化。同時(shí)使用了相同的虛擬機(jī)搭建了常用的基于XMPP協(xié)議的開(kāi)源Openfire[10]服務(wù)器,并用軟件模擬終端XMPP客戶端與服務(wù)器保持長(zhǎng)連接,進(jìn)行同樣的測(cè)試來(lái)對(duì)比。
測(cè)試結(jié)果發(fā)現(xiàn),隨著終端數(shù)的增加,Broker模塊內(nèi)存增長(zhǎng)并不明顯,每個(gè)終端的連接平均消耗11.83KB內(nèi)存;隨著終端數(shù)的增加,Openfire的內(nèi)存占用明顯增高,平均每個(gè)連接占用146.2KB,是Broker的12倍。這是因?yàn)镺penfire支持的XMPP協(xié)議較復(fù)雜,保存了很多無(wú)關(guān)數(shù)據(jù),自帶Web管理界面,因此對(duì)內(nèi)存消耗較大,而B(niǎo)roker模塊只維護(hù)連接的開(kāi)銷(xiāo)及連接與終端的映射,得益于終端推送協(xié)議的精簡(jiǎn)設(shè)計(jì)。
然后對(duì)Broker模塊的推送效率進(jìn)行了測(cè)試,同樣以O(shè)penfire作為對(duì)比,共9000個(gè)終端,每個(gè)終端發(fā)送12條push消息,共計(jì)108000條push消息。對(duì)于Broker模塊,直接向其發(fā)送push指令,不使用Facade模塊是為了避免流水落庫(kù)對(duì)實(shí)驗(yàn)結(jié)果的影響。對(duì)Openfire通過(guò)XMPP標(biāo)準(zhǔn)客戶端類庫(kù)Smack進(jìn)行模擬,在推送過(guò)程中均沒(méi)有持久化存儲(chǔ)push消息的發(fā)送流水。如表3所示。
表3 Broker模塊推送效率測(cè)試結(jié)果
Broker模塊的平均吞吐量是Openfire的2.1倍,同時(shí)Broker模塊發(fā)送的push消息通過(guò)異步補(bǔ)償?shù)姆绞酱_保無(wú)丟失,而Openfire的push消息到達(dá)率為93.77%,Openfire沒(méi)有相應(yīng)的補(bǔ)償機(jī)制。
3.2 Facade模塊的吞吐量測(cè)試
Facade模塊負(fù)責(zé)接收推送請(qǐng)求,將push消息的發(fā)送流水落庫(kù),并發(fā)送push給Broker模塊。Facade的吞吐量測(cè)試,如圖6所示。
圖6 Facade吞吐量測(cè)試
測(cè)試過(guò)程中共模擬3000個(gè)終端,向每個(gè)終端推送10條消息,實(shí)驗(yàn)有兩次,第一次由單臺(tái)(Facade模塊的)虛擬機(jī)對(duì)外發(fā)送,第二次是由兩臺(tái)虛擬機(jī)組成的集群共同發(fā)送。
圖6中發(fā)現(xiàn),單臺(tái)服務(wù)器的吞吐量為每秒872.1條,兩臺(tái)的綜合吞吐量為每秒1685.4條。在push消息的發(fā)送過(guò)程匯總,F(xiàn)acade模塊的吞吐量基本比較平滑,這是由于Facade模塊用了線程池異步提交的方式,對(duì)外暴露RocketMQ的消息接口,在推送請(qǐng)求的接收、push流水的落庫(kù)、發(fā)送push給Broker模塊這3個(gè)環(huán)節(jié)中全部異步化操作,可以緩解流量高峰,起到緩沖作用。
Facade模塊和Broker模塊在單臺(tái)服務(wù)器的吞吐量方面有較大的差距,這是由于Broker模塊精簡(jiǎn)化,但Facade模塊需要與數(shù)據(jù)庫(kù)交互。在生產(chǎn)環(huán)境中,兩個(gè)模塊分開(kāi)各自部署在集群中,需增加Facade模塊的集群數(shù)量以提高系統(tǒng)整體的吞吐量,實(shí)驗(yàn)過(guò)程中發(fā)現(xiàn)Facade集群數(shù)與Broker集群數(shù)比值為5∶1較為合適。
本文在設(shè)計(jì)終端推送服務(wù)的時(shí)候,結(jié)合商用多媒體云平臺(tái)的行業(yè)需求特征,將存儲(chǔ)發(fā)送流水、推送push消息和push消息確認(rèn)3個(gè)環(huán)節(jié)異步解耦以提高吞吐量,主要解決了推送消息可靠到達(dá)的問(wèn)題。
后續(xù)工作可以將推送服務(wù)進(jìn)一步完善,提高吞吐量,在實(shí)驗(yàn)中改進(jìn)推送效率和資源消耗問(wèn)題,嘗試將推送服務(wù)對(duì)其他云服務(wù)開(kāi)放,提供更多分析數(shù)據(jù),加強(qiáng)平臺(tái)的開(kāi)放性建設(shè)。
[1] 代超,鄧中亮.基于Netty的面向移動(dòng)終端的推送服務(wù)設(shè)計(jì)[J].軟件,2015,12:002.
[2] 吉亞云, 劉新, 葉德建. 商用多媒體信息發(fā)布系統(tǒng)持久層設(shè)計(jì)與優(yōu)化[J]. 計(jì)算機(jī)工程, 2015, 41(1): 261-265.
[3] Gudla S K, Bose J, Sunkara S, et al. A unified push notifications service for mobile devices[C]//Electronics, Computing and Communication Technologies (CONECCT), 2015 IEEE International Conference. IEEE, 2015: 1-6.
[4] 蘇毅. 移動(dòng)多媒體推送業(yè)務(wù)終端功能研究[D]. 北京:北京郵電大學(xué), 2009.
[5] Thangavel D, Ma X, Valera A, et al. Performance evaluation of MQTT and CoAP via a common middleware[C]//Intelligent Sensors, Sensor Networks and Information Processing (ISSNIP), 2014 IEEE Ninth International Conference. IEEE, 2014: 1-6.
[6] 汪海占, 邸萌, 黃祥林. 基于 XMPP 協(xié)議的 Android 消息推送設(shè)計(jì)與實(shí)現(xiàn)[J]. 科技廣場(chǎng), 2015 (2): 40-46.
[7] Sinha A, Paul N, Devarajan S. Cloud based mobile device management systems and methods: U.S. Patent 9,060,239[P]. 2015-6-16.
[8] Maurer N, Wolfthal M. Netty in Action[M]. Manning Publications, 2016.
[9] Foong A, Hady F. Storage As Fast As Rest of the System[C]//Memory Workshop (IMW), 2016 IEEE 8th International. IEEE, 2016: 1-4.
[10] Sun M, Wang S, Fang Z, et al. Design of an Instant Messaging System Based on the IaaS Cloud Platform[J]. Journal of Communications, 2015, 10(9).
Design of Terminal Push Service Based on Commercial Multimedia Cloud
Wang Yu1, Ye Dejian2
(1. Software School, Fudan University, Shanghai 201203, China;2. Engineering Research Center of Cyber Security Auditing and Monitoring, Ministry of Education, Shanghai 201203, China)
In order to meet the business needs of commercial multimedia cloud platform, we design a new terminal push service which divides the push service into three parts, i.e. the storage of push record, the delivery of push message, and the confirm of the delivery. This terminal push service realizes point-to-point delivery, the management of terminal grouping of the upper service ensures the reliable arrival of the push message. According to the experiments, this terminal push service satisfies the point-to-point grouping push demands with high push efficiency, high throughput, and stable memory usage.
Terminal push service; Reliable arrival of message; Point-to-point delivery
王鈺(1993-),女,江西,碩士研究生,研究方向:網(wǎng)絡(luò)多媒體。 葉德建(1976-),男,浙江,副教授,研究方向:網(wǎng)絡(luò)多媒體。
1007-757X(2017)06-0045-05
TP311
A
2017.04.07)