在基于位置服務(wù)的移動(dòng)應(yīng)用領(lǐng)域,移動(dòng)設(shè)備端和服務(wù)端之間總是存在大量的交互。設(shè)備向服務(wù)端發(fā)送它的位置信息和其它設(shè)備信息,服務(wù)端接收這些數(shù)據(jù),對(duì)它們進(jìn)行處理,并返回給設(shè)備端一些命令。設(shè)備端根據(jù)這些命令執(zhí)行一些操作,比如GPS數(shù)據(jù)的收集和發(fā)送頻率等。
設(shè)備端和服務(wù)端之間可以通過多種通信協(xié)議進(jìn)行交互,比如HTTP(同步)或者基于消息傳遞的異步協(xié)議。因?yàn)橐苿?dòng)網(wǎng)絡(luò)的不穩(wěn)定性,在選擇通信協(xié)議時(shí)要綜合考慮它的穩(wěn)定性和性能。同時(shí),考慮到移動(dòng)設(shè)備對(duì)電池使用時(shí)間的敏感度,最好能夠選擇一個(gè)相對(duì)比較節(jié)省資源的協(xié)議,這樣可以減少對(duì)電池的消耗。
HTTP是一種同步無狀態(tài)的協(xié)議,不支持推送,設(shè)備端需要通過輪詢模擬推送,反復(fù)的輪詢需要耗費(fèi)額外的資源。相比之下,另一種基于消息傳遞的協(xié)議MQTT在這種情況下似乎更有優(yōu)勢(shì):
MQTT可以保持設(shè)備與服務(wù)器之間的長(zhǎng)連接,避免反復(fù)的輪詢,減少資源消耗,所以更加省電 MQTT可以在設(shè)備和服務(wù)器之間建立雙向連接,從而可以使用推送有一個(gè)基于位置服務(wù)的移動(dòng)項(xiàng)目,最開始使用的是HTTP協(xié)議,但是基于上述的原因,需要使用MQTT來替換HTTP。下面來看看如何實(shí)現(xiàn)這個(gè)架構(gòu)的演變。
首先,在EC2上安裝一個(gè)Mosquitto代理。設(shè)備端把原先HTTP里的消息頭和消息體合并到一個(gè)MQTT消息里,并發(fā)送到Mosquitto代理的一個(gè)主題上。后端的API端點(diǎn)對(duì)這個(gè)主題進(jìn)行訂閱,然后處理接收到的消息。API服務(wù)對(duì)消息進(jìn)行處理后,把相應(yīng)的響應(yīng)消息發(fā)回Mosquitto代理,再推送給設(shè)備端。
不過在有多個(gè)API服務(wù)器的情況下,存在重復(fù)處理消息的問題。因?yàn)槎鄠€(gè)API服務(wù)器同時(shí)訂閱相同的主題,它們會(huì)收到一個(gè)消息的多個(gè)拷貝。為了解決這個(gè)問題,在系統(tǒng)里引入了AWS的IoT。AWS IoT在它的內(nèi)部使用了MQTT代理,同時(shí)包含了一個(gè)強(qiáng)大的規(guī)則引擎,可以利用這個(gè)引擎對(duì)Mosquitto的消息進(jìn)行處理,比如把它們保存起來,發(fā)送通知或者使用lambda函數(shù)處理消息的響應(yīng)。不過這里需要先把Mosquitto和AWS IoT橋接起來,這樣消息就可以進(jìn)入到AWS IoT。然后使用lambda函數(shù)對(duì)消息進(jìn)行處理,抽取消息里的消息頭和消息體,最后調(diào)用后端的HTTP API服務(wù)。
使用這套架構(gòu)會(huì)涉及到:
QoS - MQTT提供了三層QoS。這個(gè)是非常重要的,因?yàn)樵诘讓泳W(wǎng)絡(luò)不是很穩(wěn)定的時(shí)候,MQTT仍然能通過重試等手段保證消息可以被正確送達(dá)。 消息保留 - MQTT可以為每個(gè)主題保留最后一個(gè)消息。這對(duì)客戶端來說,可以反應(yīng)主題的狀態(tài)。 處理MQTT消息 - 設(shè)置一個(gè)Mosquitto代理并讓消息流入這個(gè)代理是很容易的,但因?yàn)槿鄙俚谌桨屢话愕囊?guī)則引擎來出來這些消息有點(diǎn)棘手。所以最后選用了AWS IoT自帶的規(guī)則引擎。 日志 - 需要對(duì)Mosquitto的日志進(jìn)行捕捉,并保存起來,方便監(jiān)控和問題定位。可以使用remote syslog來把日志傳輸?shù)絇apertrail。除了服務(wù)器端,在客戶端也需要使用MQTT的客戶端包。MQTT有各種語言客戶端,并支持Android、iOS平臺(tái)。