Vernemq Notes

Vernemq 是個 open source 的 MQTT broker,以 open source solution 來說算是功能還蠻不錯的選擇,東南亞的獨角獸gojek也有在用這套mqtt solution。
最近有遇到一些問題,順便做點筆記

Webhook loading issue

其中一個遇到的問題是 Webhook 耗用過多資源,在Gojek官方的技術blog也有提到這點。在我們這邊遇到的是該怎麼驗證這個 mqtt message 是我們所允許的合法 device 所送出來,在驗證是否為合法 device 時,已經有走了 oauth 流程,但仍須要有避免假造 message 的問題,如果都使用 webhook 去處理,會導致整個系統 cpu loading 過重。
所以後來我們的解法是在 message 裏頭做 checksum,等 message 被 sub 走之後再去驗證 checksum 是否正確。

HA of MQTT

graph LR
 Device --> |1. pub mqtt message| LB
 LB -.-> |2. sub mqtt message | service1 --> G[(DB)]
 LB <--> MQTT1
 LB <--> MQTT2

另外個問題是原本 mqtt server 只有一台,為了避免毀損導致整個 service 垮掉,改成用 Load balancer + 2台 MQTT 的架構,大致上可以參考 vernemq 的官方文件,不過在server上的設定檔以及防火牆上要特別注意。

$ vi /etc/vernemq/vernemq.conf
## add tcp listener
listener.tcp.name = 0.0.0.0:1883

nodename = node1@10.140.0.10
listener.vmq.clustering = 10.140.0.10:44053
distributed_cookie = myvmq

erlang.distribution.port_range.minimum = 6000 
erlang.distribution.port_range.maximum = 7999

另外一個 node 不一樣的部分就是 nodename 與 listener.vmq.clustering

nodename = node2@10.140.0.11
listener.vmq.clustering = 10.140.0.11:44053

要特別注意的是兩台的 distributed_cookie 要設定成一樣,然後 erlang distribution node 理論上可以不做設定,但是為了要讓防火牆可以做適當設定,所以這邊也要設定起來。

防火牆要開下面這些 port (support tls & ws)

tcp:44053
tcp:6000-7999
tcp:4369
tcp:1083
tcp:1883
tcp:8083
tcp:8883

Load balancer 部分的話,試了GCP上的 passthrough, passthrough target-pool, proxy 都可以用,

設定好之後在兩個 node 上頭啟動 vernemq,再來就可以 join cluster

# join node1@10.140.0.10 from node2
$ sudo vmq-admin cluster join discovery-node=node1@10.140.0.10

接著驗證兩台 node 是變成 cluster 做事情

$ mosquitto_sub -h LOAD_BALANCER_IP  -t 'test1' -i 'vmq1'

$ sudo vmq-admin session show # 顯示所有節點 sessions

$ sudo vmq-admin trace client client-id=vmq1
No sessions found for client "vmq1" # 代表該 client tcp session 不是建立在該節點上

# 如果有 client session 會有像下面訊息
$ sudo vmq-admin trace client client-id=vmq1
2023-12-27T02:02:01Z Starting trace for 1 existing sessions for client "vmq1" with PIDs
    [<9346.2542.0>]

# publish message 確定兩個 client 都可以收到 message
$ mosquitto_pub -h LOAD_BALANCER_IP -t 'test1' -m '9999'
$ mosquitto_pub -h LOAD_BALANCER_IP -t 'test2' -m '8888'

Reference