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'