VerneMQとEMQ Xのクラスタリング機能の挙動確認

## 目次
- 概要
- MQTTとMQTTブローカー
- VerneMQとEMQ X
- ローカルPC内にDockerでクラスタリングしてみた
- デフォルトの挙動とshared subscription
- VerneMQとEMQ Xの比較 # TODO
- ダッシュボード
- まとめ
- Appendix(作業手順)

---

## 概要

- やったこと
    - VerneMQとEMQ Xのクラスタリング機能をローカルPC内でDockerで試して、挙動を確認した

- モチベーション
    - 関わったプロジェクトで、余力があればVerneMQとEMQ Xの比較お願いしますと言われてたけど、やらなかったことが心残り
    - 特にクラスタリングが気になってたのでメインにやってみた

- 結論
    - EMQ Xの方が高機能

---

## MQTTとMQTTブローカー

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50456/107a023a-f3ad-7a94-88d2-08739e9952cc.png">

```
# MQTTとは
- IoTデバイスの通信に標準的に使用される軽量の通信プロトコル
- パブリッシュ/サブスクライブ・モデル
# MQTTブローカーとは
- サーバーとしてクライアントからのすべてのメッセージを受信し、それらのメッセージを該当する宛先クライアントにルーティング
````

---
## VerneMQとEMQ X

||VerneMQ|EMQ X|
|---|---|---|
|GitHubスター数⭐️|2k|5.6k|
|開発会社|Octavo Labs AG:flag_ch:|EMQ:flag_cn:|

- 両者とも一般的なMQTTブローカーの機能を持つ
- 両者ともマスターレスなクラスタリング機能を持つ
- MQTTブローカーのプロダクトについて下記ページにまとめられている。
    - https://github.com/mqtt/mqtt.github.io/wiki/server-support

---
### ローカルPC内にDockerでクラスタリングしてみた
---
### ローカルPC内にDockerでクラスタリングしてみた

#### 材料
- Vernemqコンテナ2個(vernemq1, vernemq2)
    - image: vernemq/vernemq (公式)

- EMQ Xコンテナ2個(emqx1, emqx2) 
    - image: emqx/emqx (公式)

- MQTTクライアントコンテナ2個(mqc1, mqc2)
    - image: HiveMQ製のmqtt-cliをインストールしたコンテナ (自作)

---
### デモ
---
### デフォルトの挙動とShared Subscription

#### デフォルト
- 受信したメッセージは、クラスタ内の全てのサブスクライバーにミラーリングされる

#### Shared Subscription
- 受信したメッセージは、クラスタ内の１つのサブスクライバーに配信される
- 配信するサブスクライバーの優先度を決めるポリシーが設定できる

---
### TODO: VerneMQとEMQ Xの比較
---
### TODO: VerneMQとEMQ Xの軽い比較

- TODO
    - ベンチマーク比較 
        - これ使えそう https://github.com/emqx/emqtt-bench
        - autoheal
        - トピックのノードルーティング
        - shared subscriptionのポリシー
        - 他観点あれば教えてください

- 現時点で観測してる範囲では、以下の点でEMQ Xが印象よかった（ただMQTTブローカーとして下記の機能がどのくらい必要かは不明）
    - コマンド豊富
    - ドキュメント充実
    - ダッシュボードがかっこいい
        - VerneMQはGraphite/Prometheusと簡単に連携できそう
    - pub/sub用のHTTP APIを持つ。
        - VerneMQもadmin用のHTTP APIはあった。

---
### VerneMQ ダッシュボード

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50456/b8c1d505-f297-ed5d-87d8-033724454391.png">

---
### EMQ X ダッシュボード
<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50456/d18cce51-e47e-a735-d0ec-c4ba105de466.png">

---

### まとめ

#### Qiitaのスライドモード初めて使った
- よいところ
    - マークダウン使える！
    - プライベートPCと会社用PCから編集できて便利！

- ここがよくなれば神！
    - スライドモードとドキュメントとしての両立
    - 文字の大きさを調節したい

---
# Appendix 作業手順
### クラスタリングしてみる

1-1. VerneMQ：起動

```
$ docker run -p 1883:1883 -p 8888:8888\
  -e "DOCKER_VERNEMQ_ACCEPT_EULA=yes"\
  -e "DOCKER_VERNEMQ_ALLOW_ANONYMOUS=on"\
  --name vernemq1\
  -d vernemq/vernemq

$ docker exec -it vernemq1 vmq-admin cluster show
+------------------+-------+
|       Node       |Running|
+------------------+-------+
|VerneMQ@172.17.0.2| true  |
+------------------+-------+
```
---

1-2. VerneMQ：クラスタリング 

```
$ docker run -p 1884:1883 -p 8889:8888\
  -e "DOCKER_VERNEMQ_ACCEPT_EULA=yes"\
  -e "DOCKER_VERNEMQ_ALLOW_ANONYMOUS=on"\
  -e "DOCKER_VERNEMQ_DISCOVERY_NODE=172.17.0.2"\
  --name vernemq2\
  -d vernemq/vernemq

$ docker exec -it vernemq1 vmq-admin cluster show
+------------------+-------+
|       Node       |Running|
+------------------+-------+
|VerneMQ@172.17.0.2| true  |
|VerneMQ@172.17.0.3| true  |
+------------------+-------+
```

---

1-3. それぞれのVerneMQブローカーをSubscribe

- mqttクライアント用Dockerfile

```
FROM centos:8

ENV PORT="1883"
ENV HOST="docker.for.mac.localhost"
ENV TOPIC="test"
ENV VERSION="3"

RUN yum install -y https://github.com/hivemq/mqtt-cli/releases/download/v1.0.0/mqtt-cli-1.0.0.noarch.rpm
CMD mqtt sub -t $TOPIC -h $HOST -p $PORT -V $VERSION
```

---
- クライアント起動してsubscribe

```
$ docker run --name mqc1 -e TOPIC="\$share/sharename/topic" -d mqtt-cli
$ docker run --name mqc2 -e PORT=1884 -e TOPIC="\$share/sharename/topic" -d mqtt-cli 
```

- pub

```
$ mqtt pub -t topic -m piyopiyo
```

---

### EMQ X

```
$ docker run -d --name emqx1 -e EMQX_LISTENER__TCP__EXTERNAL=1883 -e EMQX_NAME="emqx" -e EMQX_HOST="172.17.0.2" -e EMQX_JOIN_CLUSTER="emqx@172.17.0.2"  -p 18083:18083 -p 1883:1883 emqx/emqx

$ docker run -d --name emqx2 -e EMQX_LISTENER__TCP__EXTERNAL=1883 -e EMQX_NAME="emqx" -e EMQX_HOST="172.17.0.3" -e EMQX_JOIN_CLUSTER="emqx@172.17.0.2"  -p 18084:18083 -p 1884:1883 emqx/emqx

$ docker exec -it emqx1 ./bin/emqx_ctl cluster join emqx@172.17.0.3
```

### Shared Subscription

```
$ docker run --name mqc1 -e TOPIC="\$share/group/up/data" -d mqtt-cli

$ docker run --name mqc2 -e PORT=1884 -e TOPIC="\$share/group/up/data" -d mqtt-cli

$ mqtt pub -t up/data  -m piyopiyo
```

---
### 参考
vernemq docker https://github.com/vernemq/docker-vernemq
shared subscription https://docs.vernemq.com/configuration/shared_subscriptions

emqx docker https://github.com/emqx/emqx-rel/tree/master/deploy/docker

emqx クラスタ設定方法 https://docs.emqx.io/tutorial/v3/en/cluster/setup_start.html