MQTT 共有サブスクリプション
EMQX は MQTT の共有サブスクリプション機能を実装しています。共有サブスクリプションは複数のサブスクライバー間で負荷分散を実現するためのサブスクリプションモードです。クライアントは複数のサブスクリプショングループに分けられ、メッセージはすべてのサブスクリプショングループに転送されますが、各グループ内のクライアントのうち1つだけがメッセージを受信します。元のトピックにプレフィックスを付けることで、複数のサブスクライバー向けの共有サブスクリプションを有効にできます。EMQX は共有サブスクリプションのプレフィックスとして、グループ用($share/<group-name>/
で始まる)とグループ用でないもの($queue/
で始まる)の2種類の形式をサポートしています。
共有サブスクリプションの2種類のプレフィックス形式の例は以下の通りです。
プレフィックス形式 | 例 | プレフィックス | 実際のトピック名 |
---|---|---|---|
グループ用共有サブスクリプション | $share/abc/t/1 | $share/abc/ | t/1 |
グループ用でない共有サブスクリプション | $queue/t/1 | $queue/ | t/1 |
クライアントツールを使って EMQX に接続し、このメッセージングサービスを試すことができます。本節では共有サブスクリプションの仕組みを紹介し、MQTTX Desktop と MQTTX CLI を使ってクライアントをシミュレートし、共有サブスクリプション機能を試す方法を説明します。
グループ用共有サブスクリプション
元のトピックに $share/<group-name>
のプレフィックスを付けることで、グループ単位の共有サブスクリプションを有効にできます。グループ名は任意の文字列です。EMQX は異なるグループに同時にメッセージを転送し、同じグループに属するサブスクライバーは負荷分散しながらメッセージを受信します。
例えば、サブスクライバー s1
、s2
、s3
がグループ g1
のメンバーで、s4
と s5
がグループ g2
のメンバーであり、全員が元のトピック t1
をサブスクライブしているとします。共有サブスクリプショントピックは $share/g1/t1
と $share/g2/t1
になります。EMQX が元のトピック t1
にメッセージ msg1
をパブリッシュすると:
- EMQX は
msg1
をグループg1
とg2
の両方に送信します。 s1
、s2
、s3
のうちの1つだけがmsg1
を受信します。s4
とs5
のうちの1つだけがmsg1
を受信します。

グループ用でない共有サブスクリプション
$queue/
プレフィックスの共有サブスクリプショントピックは、グループに属さないサブスクライバー向けのものです。これは $share
プレフィックスを使った共有サブスクリプションの特殊なケースと考えられます。すべてのサブスクライバーが $share/$queue
のようなサブスクリプショングループに属していると理解できます。

共有サブスクリプションとセッション
クライアントがパーシステントセッションを持ち、共有サブスクリプションをサブスクライブしている場合、クライアントが切断している間もセッションは共有サブスクリプショントピックにパブリッシュされたメッセージを受信し続けます。クライアントが長時間切断状態にあり、メッセージのパブリッシュ頻度が高いと、セッション状態内の内部メッセージキューがオーバーフローする可能性があります。この問題を避けるために、共有サブスクリプションにはクリーンセッション(clean_session=true
)を使用することを推奨します。クリーンセッションはクライアント切断後すぐに期限切れになります。
MQTT v5 を使用する場合は、セッション有効期限を短く設定する(0以外の場合)ことが推奨されます。これにより、クライアントは一時的に切断しても、切断期間中にパブリッシュされたメッセージを再接続後に受信できます。セッションが期限切れになると、送信キュー内の QoS1 および QoS2 メッセージ、またはインフライトキュー内の QoS1 メッセージは同じグループの他のセッションに再配信されます。最後のセッションが期限切れになると、すべての保留中メッセージは破棄されます。
パーシステントセッションの詳細は、MQTT Persistent Session and Clean Session Explained を参照してください。
MQTTX Desktop で共有サブスクリプションを試す
前提条件
- MQTT の 共有サブスクリプション に関する知識
- MQTTX を使った基本的なパブリッシュとサブスクライブ操作の理解
以下の手順では、元のトピックに $share
プレフィックスを付けて、異なるグループのサブスクライバーが同じトピックの共有サブスクリプションを行い、共有サブスクリプションからメッセージを受信する方法を示します。
このデモでは、1つのクライアント接続 demo
をパブリッシャーとして作成し、トピック t/1
にメッセージをパブリッシュします。さらに、Subscriber1
、Subscriber2
、Subscriber3
、Subscriber4
の4つのクライアント接続をサブスクライバーとして作成します。サブスクライバーはグループ a
と b
に分けられ、両グループがトピック t/1
をサブスクライブします。
EMQX と MQTTX Desktop を起動し、New Connection をクリックしてパブリッシャー用のクライアント接続を作成します。
- Name に
Demo
を入力します。 - Host にローカルホストの
127.0.0.1
を入力します(本デモの例として)。 - 他の設定はデフォルトのままにして Connect をクリックします。
TIP
MQTT 接続の作成方法の詳細は MQTTX Desktop を参照してください。
- Name に
New Connection をクリックして、4つのサブスクライバー用の接続を作成します。Name はそれぞれ
Subscriber1
、Subscriber2
、Subscriber3
、Subscriber4
に設定します。Connections ペインでサブスクライバー接続を1つずつ選択し、New Subscription をクリックして共有サブスクリプションを作成します。以下のルールに従って、Topic テキストボックスに正しいトピックを入力します。
複数のサブスクライバーをグループ化するには、サブスクライブするトピック
t/1
の前にグループ名{group}
を追加します。さらに、すべてのグループ名の前に$share
プレフィックスを付けます。New Subscription ウィンドウで:
Subscriber1
とSubscriber2
の Topic を$share/a/t/1
に設定します。Subscriber3
とSubscriber4
の Topic を$share/b/t/1
に設定します。
これらの例のトピックでは:
- プレフィックス
$share
は共有サブスクリプションであることを示します。 {group}
はa
とb
で、任意の名前に変更可能です。t/1
は元のトピック名を示します。
他の設定はデフォルトのままにして、Confirm ボタンをクリックします。
先ほど作成した
Demo
接続をクリックします。トピック
t/1
でメッセージを送信します。グループa
のクライアントSubscriber1
とグループb
のクライアントSubscriber4
がメッセージを受信するはずです。同じメッセージを再度送信します。グループ
a
のSubscriber2
とグループb
のSubscriber3
がメッセージを受信します。
TIP
共有サブスクリプションのメッセージがパブリッシュされると、EMQX は異なるグループに同時にメッセージを転送しますが、同じグループ内のサブスクライバーのうち1つだけがメッセージを受信します。
MQTTX CLI で共有サブスクリプションを試す
4つのサブスクライバーを2つのグループに分けて、トピック
t/1
をサブスクライブします:bash# クライアント A と B がトピック `$share/my_group1/t/1` をサブスクライブ mqttx sub -t '$share/my_group1/t/1' -h 'localhost' -p 1883 ## クライアント C と D がトピック `$share/my_group2/t/1` をサブスクライブ mqttx sub -t '$share/my_group2/t/1' -h 'localhost' -p 1883
新しいクライアントを使って、元のトピック
t/1
にペイロード1
、2
、3
、4
の4つのメッセージをパブリッシュします:bashmqttx pub -t 't/1' -m '1' -h 'localhost' -p 1883 mqttx pub -t 't/1' -m '2' -h 'localhost' -p 1883 mqttx pub -t 't/1' -m '3' -h 'localhost' -p 1883 mqttx pub -t 't/1' -m '4' -h 'localhost' -p 1883
各サブスクリプショングループ内のクライアントが受信したメッセージを確認します:
- サブスクリプショングループ1(A と B)およびサブスクリプショングループ2(C と D)は同時にメッセージを受信します。
- 同じグループ内のサブスクライバーのうち1つだけがメッセージを受信します。