emq實現向大量指定設備推送消息(九)

前言:最近完成了一個需求,向大量的指定設備推送消息。但是,實現過程中發生一些問題,導致不得不換了一種實現方式,故記錄之,以供參考。


先說明下背景:emq集羣爲2個節點,配置爲4核16G,同時在線設備量大概在10W左右(即每個節點負載約5W)。

需求就是:需要向這其中的某3萬設備推送某個消息。

解讀下需求:比如我現在有設備號碼是 1-100000 的這麼些設備,要推送 30000-60000 的這些設備一些消息。

怎麼實現呢?

目前有兩種思路,且聽我一一道來。

思路一:利用emq的保留消息實現。這也是我第一次想到並付諸於實踐的思路。

保留消息的特點是,發佈到topic的消息如果是保留消息的話,那麼訂閱這個topic的設備上線後將收到此消息。

那麼可以這樣設計:

設備端,每個設備都訂閱自己獨有的topic,例如用自己唯一的設備號,比如

1號設備訂閱:private/1

2號設備訂閱:private/2

這樣在發佈的時候,就可以向上面 private/30000 到 private/60000 這些topic發佈保留消息,然後也只有對應訂閱了這些topic的設備能收到了。

但是,嘿嘿,凡事都有但是。這種實現有兩個問題:

1,鑑於保留消息的機制(一個topic只保留一條最新消息),同時只能像某個設備推送一條消息,舉個例子:

在向 private/1 發了保留消息推送第一條消息【1號1號,再不上線就分手!】時,若1號設備一直不在線,而這時候你等不及又推了第二條消息【都是你的錯!分手吧!】。這時如果1號設備聯網上線了,就只會收到第二條消息,到最後也不知道爲啥被分了手。

2,emq服務器在上述背景下,推送幾千條的保留消息,就會把cpu跑滿!這個問題,我反饋諮詢過emq的開發人員,emq存數據是用的mnesia數據庫,如果有大量保留消息的時候,每個設備上線時,都會到這個庫查看是否有此設備所訂閱topic匹配的路由數據。我的理解是,emq在存在大量保留消息,且上下線頻繁的場景下,還做的不夠好。

思路二:利用 redis+emq的上下線數據 實現。

鑑於保留消息有以上的問題,肯定行不通了,後來有想到一種思路。解決了這個問題。

設計思路:

設備端,每個設備訂閱自己獨有的topic,這個不變。

而發佈端,不再發保留消息到emq,而是發到redis。在redis內,爲每個設備維護一個待推送數據列表。利用redis的set數據結構來實現。比如:

1號設備的待推送列表爲set結構的,key的結構爲:retain:1

然後往這個key裏面存要發佈的指令,然後再利用emq的上下線消息,一上線,就去redis查 retain:1 下有沒有待推送數據,有就推送,這樣就實現了向獨立設備推送獨立消息的需求。推完之後可以刪掉此消息,或者再設計一個回執反饋,待設備發回了某些特定回執之後再刪也可以。並且,set結構的key能夠存多條數據,只要內容不一樣,所以可以解決上面保留消息第一點的問題

至於上面第二點的問題,redis數據存在內存,吞吐極大,性能沒有問題。

以上,筆者用第二種方式實現了上述背景下的需求,經過長時間驗證,性能和可持久性都可靠。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章