EMQ 是一款基于高并發(fā)的 Erlang/OTP 語言平臺設計,支持百萬級連接和分布式集群窘行,發(fā)布/訂閱模式的開源MQTT消息服務器。
EMQ 單節(jié)點支持100萬并發(fā)MQTT連接峰值負載加派,超過了絕大多數(shù)的后端服務對消息的處理能力熟尉。因此往往需要多個后端服務節(jié)點來分擔。但是基于的 MQTT 3.1.1 協(xié)議標準熙卡,如果多個后端服務節(jié)點訂閱了相同的 topic杖刷,來自這些 topic 消息會被同時派發(fā)給所有的后端服務。為了解決這樣的問題驳癌,EMQ 提供了共享訂閱這個機制滑燃。
共享訂閱 (Shared Subscription) 是指在多訂閱者間采用分組負載平衡方式派發(fā)消息
EMQ 提供了如下兩種共享訂閱的方式:
- $queue/ 隊列共享訂閱
- $share/<group/ 分組共享訂閱
隊列共享訂閱是指以 $queue/ 開頭的 topic 例如 $queue/topic1,如果有多個客戶端同時訂閱了颓鲜,EMQ 會把發(fā)送到 topic1 的消息以負載均衡的方式派發(fā)給所有客戶端表窘,保證一條消息只會派發(fā)給一個客戶端。需要注意前綴 $queue 只適用于訂閱時甜滨,發(fā)布消息時不需要乐严。
分組共享訂閱是一個更加靈活的方式,實現(xiàn)方式為所有以 $share/<group>/ 開頭的的 topic 會以 group 來分組進行消息的負載均衡派發(fā)衣摩。例如有4個客戶端依次訂閱了$share/group1/topic1昂验,$share/group1/topic1,$share/group2/topic1 和 $share/group1/topic1艾扮。所有發(fā)送到 topic1 的消息會被同時派發(fā)到分組 group1 和 group2既琴,但是兩個分組中的每次都只會有一個客戶端收到消息。同樣前綴$share/<group>/ 只適用于訂閱時泡嘴,發(fā)布消息時不需要甫恩。
以上都是基于單個 EMQ 節(jié)點的共享訂閱方法,在多個 EMQ 節(jié)點組成的集群環(huán)境下也能實現(xiàn)共享訂閱的消息只會到達一個或者每組中的一個訂閱客戶端嗎酌予?
很遺憾填物,答案是不能。雖然 EMQ 能簡單的通過 HAProxy 來搭建分布式集群霎终,但是直到最新的 2.3.11 版本滞磺,都沒有支持集群環(huán)境下的共享訂閱。如果在集群中使用共享訂閱莱褒,在消息到達時击困,集群機制會把消息發(fā)送到每個 EMQ 節(jié)點上,隨后每個 EMQ 節(jié)點會把消息以負載均衡的方式派發(fā)給與自己建立連接的訂閱客戶端。換句話說阅茶,集群環(huán)境中的每個節(jié)點上都會有一個或者每組一個訂閱客戶端收到共享訂閱的消息蛛枚。
幸運的是,結(jié)合 EMQ 提供的本地訂閱機制可以實現(xiàn)脸哀,可實現(xiàn)偽集群下的共享訂閱蹦浦。
本地訂閱(Local Subscription) 只在本節(jié)點創(chuàng)建訂閱與路由表,不會在集群節(jié)點間廣播全局路由
本地訂閱的方式跟隊列共享訂閱很相似撞蜂,都是在普通的 topic 前加上固定的前綴盲镶。本地共享訂閱的前綴是 $local/。
使用本地共享訂閱以后蝌诡,來自訂閱的 topic 的消息只會在消息發(fā)布客戶端連接的 EMQ 節(jié)點上進行派發(fā)溉贿,也就做到了只有這個節(jié)點上一個或者每組中的一個共享訂閱客戶端收到消息。
如果消息發(fā)布客戶端所在的 EMQ 節(jié)點上沒有訂閱客戶端浦旱,由于本地訂閱的特性宇色,其他節(jié)點上訂閱客戶端也無法收到消息。因此必須保證 EMQ 集群中的每個節(jié)點上都至少得一個本地共享訂閱客戶端才能達真正意義上的共享訂閱颁湖。
由于該實現(xiàn)機制要求每個 EMQ 節(jié)點上都有共享訂閱客戶端宣蠕,結(jié)合業(yè)務就是要求每個 EMQ 節(jié)點上至少有一個消息處理服務連接,考慮備份則每個節(jié)點需要至少兩個服務甥捺。擴容 EMQ 節(jié)點需要同時對服務節(jié)點相應擴容植影,因而稱該實現(xiàn)方式為偽集群環(huán)境下的共享訂閱。
EMQ 官方團隊已經(jīng)表明會在下次大版本更新時支持集群下的共享訂閱涎永,因此如果目前單 EMQ 節(jié)點足夠支撐業(yè)務需求可延緩集群化時間思币,等待下個大版本更新的發(fā)布。