1. 程式人生 > >MQTT(mosquitto)

MQTT(mosquitto)

以前大多數im都使用私有協議, 後來發展出開放的xmpp, 使用xml通訊, 不用說消耗網路資源太大了。
我本來想使用protobuf自定義一套私有協議,但想到工作量還是太大,然後發現現在mqtt協議很熱門,特別是物聯網使用比較多,不過也可以用來做im訊息推送伺服器。

MQTT開源專案

上github搜尋golang的mqtt伺服器,找到最多star的surgemq,不過一看居然三年沒有更新了,作者也不大可能繼續維護,在其Issues的一個問題中找到作者的答覆說推薦另一個人fork的專案volantmq,不過在網上沒有搜尋到過於這個專案的文章,所以還是放棄了。
最後發現mosquitto

,這是一個eclipse專案組用c語言寫的, 更新比較頻繁,雖然網上討論說也有是點問題,但還是暫選擇這個專案做為mqtt伺服器。
至於客戶端,先考慮IOS上的實現,當然是找swift語言編寫的,因為實在噁心objc的語法,找到這個CocoaMQTT應該還不錯。

安裝mosquitto

暫時還用不著改mosquitto程式碼,直接安裝可執行程式就行。
mac下:

brew install mosquitto
mosquitto

如果執行mosquitto失敗,則
brew info mosquitto
發現可執行檔案在usr/local/Cellar/mosquitto/1.4.14_2/sbin/mosquitto

brew安裝的mosquitto不支援websocket,要想支援需要自己編譯。

安裝CocoaMQTT

很簡單,支援pod,根據CocoaMQTT官方說明直接pod就好,有可能pod下載下來的版本過低,使用pod update後會得到比較新的版本。

MQTT QoS

QoS Level 0:至多一次
意思就是給你轉發一次就得了,不管你有沒收到。
這個我理解是如果接收方離線了就不能收到訊息,可以用在音視訊聊天請求,因為當接收方離線後就不用收到請求了,就算是接收方線上但是沒有收到訊息也可以通過傳送方超時來重發請求。
image

QoS Level 1:至少一次,有可能重複


也就是說伺服器給你重試轉發,直到伺服器收到客戶端的確認訊息。
確保至少向客戶端傳送一次資訊,不過也可傳送多次;在接收資料包時,需要客戶端返回確認訊息(ACK 包)。這種方式常用於傳遞確保交付的資訊,但開發人員必須確保其系統可以處理重複的資料包。
這個可以用在普通文字聊天, 接收方離線後,伺服器自動快取訊息,等接收方上線時伺服器馬上把訊息推送給他,就算是接收方重複收包也沒關係因為可以通過訊息裡包含的時間來過濾掉。這個級別的訊息伺服器得注意限制傳送方的訊息大小和數量,免得伺服器記憶體被爆掉。
image

QoS Level 2:只有一次,確保訊息只到達一次
伺服器保證你肯定能收到一次,而且只有一次。
這個用在訊息重要性比較嚴格的場合。IM在一般情況下用不著,或者在使用者發生金錢消費有關的情況下可以使用?
image

MQTT在IM中的用法

MQTT的協議格式

關於主題Topic

主題的設計應該是系統的核心,(可參考MQTT Part 5 主題和最佳實踐,順便可以看看這個blog的MQTT文章。)

每個主題必須包含至少一個位元組,並且它還可以包含空格。 另外,主題是區分大小寫的,這使得myhome/temperature和MyHome/Temperature是兩個單獨的主題。除此之外,單獨的正斜線也是有效的主題。

主題是utf8字串,太長的主題會佔用較多的網路資源,我想真正專案中對於網路流量比較敏感時應該對主題名字做優化,使用超短的字元,比如每層都只用一個字元來表示。為了提高可讀性,平常程式碼都使用有意義的長字元,內部使用定義message type的方式把每層對映到1個位元組,這樣保持可讀性又大大縮短主題名字的長度,減小佔用網路流量。
只取ASCII表128來對映層名,去除33個控制字元和MQTT的保留字元:/, #, +以外,還有92個字元可以使用,可以再去掉一些符號比如空格、正斜杆,星號等,應該還是可以滿足需求了,如果不夠就再加一個字元唄。
當然對於動態名比如使用者ID之類的還是得用原本字串而不能使用對映。

mosquitto外掛擴充套件

參考文章