天天看點

開源MQTT中間件:moquette

經測試過程發現moquette存在一些問題,已修改,可能是認識的問題,也可能是出發點不一樣。

總之,修改如下: 

1. 修改消息隊列長度為32,避免了原來消息隊列超過最大條數之後,publish出錯的情況 修改了storage的構造函數,使其更通用 

2. 修改了每次都對clientId的判定,針對client首次連結的情況 修改了離線消息簽收時的空指針異常 棄用了一些不常用的子產品 

3. 添加了redis存儲實作 redis采用了現有conf配置機制 重新設計了session的存儲結構,以便後續添加分片處理 

4. 修改工程的結構,獨立了common子產品,同時将redis,mapdb,broker建在common基礎上 

5. 針對publish的記憶體洩漏,進行了修改(原本以為是netty洩露),經過兩天的不眠不休的調試,發現是moquette未回收導緻

使用說明文檔:

1.簡介

Moquette是一款開源的消息代理,整個系統基于java開發,以netty為基礎完整實作了MQTT協定的。 

基于測試,moquette的用戶端承載量及消息的推送速度都比較客觀,在大批量頻繁短線上線的情景下,也可以承受。 

Moquette代碼是完全開源的,測試過程中的問題進行了一定的修改,擴充實作了基于redis存儲的機制。

2.使用

Moquette所使用的配置檔案位于其根目錄下的config裡,包括以下:

acl.conf 權限配置

hazelcast.xml 叢集配置

password_file.conf 使用者密碼配置

moquette.conf 主配置

下面将詳細講解各配置檔案

基于檔案的權限配置較為複雜,以下為示例格式,将針對該示例具體說明。

1

2

3

4

5

6

7

8

[user admin] 訓示一個使用者admin。其後的條目,代表該使用者的相關topic的讀寫權限,一直到另一個user結束。

[topic write wifi/log] 代表隊wifi/log主題具有write權限,topic指令指定特定的主題名稱,不能帶有通配符。

[pattern write wifi/log/+] 使用通配符訓示符合規則的一定數量的topic的權限。 

權限分類: 

write

read

writeread

Moquette的叢集配置實用的是hazelcast。Hazelcast是基于java編寫的資料同步工具。在moquette中,用于不同節點消息的同步。

9

10

public-address:代表了目前節點的IP及端口 

required-member:代表了叢集中的其他節點。 

各節點的叢集模式建立後,各節點是對等關系,無主從之分

該檔案用于系統的可登入使用者,執行個體格式如下:

該檔案的格式非常簡單: 

每行代表了一個使用者及其密碼,用:分割,密碼是sha256摘要後的結果。

關于client(消費者)所使用的使用者,大部分情況下,client隻需要其clientId來區分,是以背景可針對業務類型建立不同的使用者分給client使用,不需要為每個clientId都建立使用者。

主配置中包含了較多内容,介紹如下:

port 1883 是broker的主端口,預設為MQTT協定的1883端口 

由于系統提供了websocket功能,可以使用websocket的方式使用(該模式未進行測試)。

對于有較高安全要求的系統,可以添加SSL支援。

storage_class io.moquette.persistence.redis.RedisStorageService 

由于基于不同存儲的實作的性能,差異性較大,moquette預設采用記憶體存儲的模式,該模式有很高的性能,但存在單點崩潰下,消息丢失的風險(由于叢集負載的使用,可降低該問題發生的影響範圍)。 

如果對存儲過于看重,性能可求次,可使用基于redis的存儲實作,其自帶的mapdb的存儲實作,錯誤較多。 

在不設定的情況,預設采用的基于memory的存儲實作。

以上代表了,broker将以acl.conf中的内容為基礎進行授權鑒權。

以上代表不允許匿名通路,必須使用使用者名及密碼才可以通路。

以上代表broker将使用password檔案進行鑒權,若不需要則可以将其注釋掉。

在linux系統下,提供的epoll機制,可使系統能夠承載更高的終端。以上代表啟用epoll。在機器硬體較好的情況下,epoll模式提升明顯。

叢集配置的情況下,需要開啟以上配置,開啟配置的前提是hazelcast.xml檔案已配置。

在store_class已經配置為redis的情況下,需要配置以上參數,由于叢集模式使用hazelcast,目前的基于redis的實作,不具備分片等功能,但鍵值的設計已經具備。

Moquette代碼工程采用maven管理,采用maven install可以打包一個在linux下運作的檔案,打包後的格式如下:

Lib目錄是所有使用到的lib檔案,分為: 

Netty相關

Hazelcast

Log相關

Redis存儲實作引入的lib:在使用memory的模式下,redis相關可以删除,減少包的大小。

Bin目錄: 

開源MQTT中間件:moquette

linux下的moquette.sh啟動方式: 

預設不是以背景運作的方式,需要使用以下指令運作:

nohup指令模式會找不到配置好的log輸出。 

Windows下以bat指令運作

實作moqtt協定的用戶端存在很多種,針對該broker,目前測試使用的是eclipse-phao的,該用戶端實作提供了多種語言版本,便于不同終端使用。

可以在以下的網址中找到相關語言版本的下載下傳:​​http://www.eclipse.org/paho/downloads.php​​

針對不同的語言版本,可提供的功能存在不同,目前broker預設沒有實作除mqtt協定規範中提到的功能。

重連機制,需要用戶端想法實作該機制,避免用戶端掉線後隻能重新開機才能連結的境界。

開源MQTT中間件:moquette

3. 測試

該broker經過了多次測試。 

測試場景:

<col>

記憶體

CPU

8G

4核

Client所運作機器多樣,每台機器運作5000個client。 

Publish為普通windows機器,兩個publisher,每個5個發送線程,平均每秒100條消息。

10秒一條群發的情況下,測試3論。

每秒100條點對點的消息情況下,測試3輪。

每輪測試20到30幾個小時。

Client在clean Session的情況下,broker的記憶體占用較低,僅400M左右 

在不清理會話的情況下,記憶體占用較高,在client大批量反複掉線重連情況下記憶體占用達到2G 

心跳設定60s,過短(低于30s)的心跳,對broker來說不能承受。

搭建了兩個節點的叢集,通過nginx進行tcp負載,用戶端測試數量為3萬。

1.單broker從8000,15000,18000,25000幾個級别的測試,在不發送消息的情況下,這幾個級别的用戶端都可以連接配接。

承載量

結果

8000

OK

15000

18000

25000

2.在發送消息的情況

NG

在每10秒一條群發消息的情況下,單點broker的無掉線承載量是15000,18000發生較多的掉線情況。

在10秒一條群發消息及每秒100條點對點消息的發送情況下,消息的接受速度都在1秒以内。

基于實作分析,記憶體的占用主要由client在不清理會話進行連結掉線後産生的消息積累,在原有基于記憶體的實作機制中,為每個client儲存1024條消息,在超過1024條後,消息會導緻publish端出錯。修改後的實作,為每個離線client儲存最新的32條消息,超過32條的将被丢棄。

基于redis的實作,消息目前沒有設定棄用或過期機制。

測試期間的記憶體分析: 

IP1的broker,總記憶體占用情況如下 

開源MQTT中間件:moquette
開源MQTT中間件:moquette

記憶體穩定在800M左右,處于穩定狀态。

基于記憶體的存儲實作,目前僅儲存32條離線消息,超過32條将丢棄原有的。

遺願消息内容必須為ascii,不能為其他字元。遺願消息主要用于用戶端掉線後的處理。

用戶端的心跳不能設定過小,否則broker的承載量将嚴重下降,建議60s以上。

遺留的問題:

在心跳之間的時間段,測試發現存在broker誤簽收的情況。

以上問題,在業務實際使用過程中,采取業務簽收等方式,避免消息品質的不可靠性的出現。

繼續閱讀