天天看點

我的mqtt協定和emqttd開源項目個人了解(18) - 一個用戶端sub很多主題和資料,出現當機?使用本地共享訂閱解決!

我的mqtt協定和emqttd開源項目個人了解(18) - 一個用戶端sub很多主題和資料,出現當機?使用本地共享訂閱解決!
我的mqtt協定和emqttd開源項目個人了解(18) - 一個用戶端sub很多主題和資料,出現當機?使用本地共享訂閱解決!

EMQ中CPU是公平配置設定給MQTT會話,大量pub消息到一個訂閱,訂閱不會拿到更多cpu,最終導緻消息累積,記憶體溢出當機。

最好的解決辦法是分組訂閱,把消息打散,多個用戶端訂閱。

問:請問一下,我現在的業務就是隻使用一個sub,主題是\hello\#,去訂閱數萬個終端消息。請問針對這個問題,如何來優化業務邏輯?可以通過增加sub的方式嗎?即把數萬終端分成幾個小組,每小組往一個主題pub,然後再分别訂閱?

答:不需要自己實作,使用emq 2.x的本地+共享訂閱相結合即可。使用主題:$local/$share/group/topic

http://emqtt.com/docs/v2/advanced.html#local-subscription

emq2.x版本,共享訂閱隻支援單節點,不支援叢集。

---

關聯閱讀:我的mqtt協定和emqttd開源項目個人了解(24) - emq v2.3.11源碼成熟度如何?

EMQ 2.3中的本地/共享訂閱

簡介

使用本地訂閱後,指消息隻在訂閱者的本地(所連接配接的)EMQ節點,不會流傳到叢集中的其它EMQ節點中。在共享訂閱中,訂閱同一個主題的用戶端會輪流的收到這個主題下的消息,也就是說同一個消息不會發送到多個訂閱者,進而實作訂閱端的多個節點之間的負載均衡。共享訂閱對于資料采集/集中處理類應用非常有用。在這樣的場景下,資料的生産者遠多餘資料的消費者,且同一條資料隻需要被任意消費者處理一次。

EMQ中本地/共享訂閱特性

本地訂閱(Local Subscription)是指隻在本節點建立訂閱與路由表,不會在叢集節點間廣播全局路由。

mosquitto_sub  -t  '$local/topic'

mosquitto_pub  -t  'topic'

使用方式: 訂閱者在主題(Topic)前增加‘$local/’字首。

共享訂閱(Shared Subscription)支援在多訂閱者間采用分組負載平衡方式派發消息:

共享訂閱支援兩種使用方式:

訂閱字首 使用示例

$queue/ mosquitto_sub -t ‘$queue/topic’

$share/<group>/ mosquitto_sub -t ‘$share/group/topic’

其中$queue與$share的差別,在于$share後面可以加不同的分組(group),比如$share/group1/topic,$share/group2/topic,$share/group3/topic,生産者發一個topic的消息,訂閱$share/group1/topic的消費者、$share/group2/topic的消費者、$share/group3/topic的消費者都能收到消息,如果一個分組中存在多個消費者,則多個消費者還會共享訂閱消息,每個group的消息随機其中一個消費者能獲得。

使用場景

當生産者和消費者的消息隻想通過一個EMQ節點,可使用EMQ的本地訂閱。

當消費者的消息想通過EMQ實作訂閱端的多個消費者之間的負載均衡,則可使用EMQ的共享訂閱。

特殊情況下,當多個生産者生産多條消息的時候,一個消費者壓力會很大,分擔一個消費者的壓力,或者其它情況,需要用到本地共享訂閱。本地共享訂閱是本地訂閱與共享訂閱的組合。

下圖為本地共享訂閱的消息走向和訂閱關系。每個消費者都必須本地共享訂閱每一個EMQ節點,這樣每條消息隻會走向一個消費者。注意:這裡的SUB指消費者,PUB指生産者。

消息流向

每個PUB的消息從經過LB(負載均衡),發送到不同的EMQ節點中,比如第一個EMQ節點收到的M1、M3、M4的消息:

通過本地訂閱,這個EMQ節點的消息把收到的M1、M3、M4的消息不發給其它叢集的EMQ節點,隻從這個EMQ節點發送給訂閱的SUB。

通過共享訂閱,這個EMQ的消息把收到的M1、M3、M4的消息發送給不同的SUB端。

通過上述本地訂閱+共享訂閱,實作多個PUB發送的每條消息随機到達一個并且隻有一個SUB。

訂閱關系

每個SUB使用本地共享訂閱($local/$share/A)來訂閱EMQ叢集中的每個EMQ節點。