Skip to content

EMQX クラスタリング

EMQX クラスタリングとは、複数の EMQX ノードを連携させて統一されたシステムとして動作させるデプロイメントを指します。これらのノードはクライアントのセッション、トピックのサブスクリプション、およびルーティング情報を自動的に共有し、シームレスなメッセージ配信と水平スケーラビリティを実現します。

注意

クラスタリング機能はトライアル期間中に利用可能です。トライアル終了後は商用ライセンスが必要であり、ライセンスがない場合は機能が無効になります。

本章では、クラスタリングの利点、新しいMria と RLOG アーキテクチャ、クラスタの手動または自動作成方法ロードバランシングの実装方法、およびクラスタ内の通信セキュリティの確保方法を紹介します。

このアーキテクチャは、MQTT を基盤とした大規模かつミッションクリティカルな IoT およびメッセージングプラットフォームに最適です。

章の概要

本章では EMQX クラスタリングの包括的な概要と実際のデプロイメントへの適用方法を解説します。以下の内容を学べます:

高可用な MQTT プラットフォームを構築する場合や本番規模の準備をする際に、自信を持って始められるガイドです。

なぜ EMQX クラスタリングを使うのか

EMQX クラスタリングは、信頼性、スケーラビリティ、およびパフォーマンスを求める大規模かつミッションクリティカルなアプリケーション向けに設計されています。主な利点は以下の通りです:

  • スケーラビリティ:ノードを追加することで容易にデプロイメントを拡張でき、EMQX は増加する MQTT クライアントとメッセージをサービス停止なく処理可能です。
  • 高可用性:分散アーキテクチャにより単一障害点がなく、1つ以上のノードがオフラインになってもシステムは継続して動作します。
  • ロードバランシング:MQTT トラフィックとクライアントセッションをノード間で分散し、ボトルネックを防ぎハードウェアの利用効率を最大化します。
  • 集中管理:すべてのノードを単一のダッシュボードまたは API エンドポイントから管理・監視でき、運用と保守が簡素化されます。
  • データの一貫性とセキュリティ:セッションおよびルーティング状態はノード間で自動的に複製され、一貫性を保ちつつクラスタ全体で安全な通信を維持します。

EMQX クラスタリングの仕組み

EMQX クラスターは複数のノードで構成され、それぞれが EMQX のインスタンスを実行しています。これらのノードは連携してメッセージのルーティング、MQTT セッションの管理、高可用性とスケーラビリティの確保を行います。各ノードは他のノードと通信し、クライアントのサブスクリプションやルーティング情報を共有することで、どのノードに接続されたクライアントにもメッセージが届くようにします。

この分散設計により、EMQX はミッションクリティカルなメッセージングシステムを最小限のダウンタイムで柔軟に拡張可能です。

クラスタアーキテクチャの進化

EMQX 5.0 以前:Mnesia ベースのクラスタリング

初期の EMQX は Erlang/OTP に組み込まれた Mnesia データベースとフルメッシュトポロジーを利用していました。各ノードは Erlang 分散プロトコル(デフォルトポート:4370)を使い、すべての他ノードと直接 TCP 接続を維持し、密結合のシステムを形成していました。

mnesia-cluster

しかし、このモデルには以下の制約がありました:

  • クラスタサイズの増加に伴う高い同期オーバーヘッド
  • 5ノード以上のクラスタでの不安定性リスク
  • 垂直スケーリングによるスケーラビリティの限界

EMQX 4.3 はベンチマークテストで 1000万同時接続を達成しましたが、高度なチューニングと高性能ハードウェアが必要でした。詳細はパフォーマンスレポートを参照してください。

EMQX 5.0 以降:Mria + RLOG

バージョン 5.0 からは、新しいMria クラスタアーキテクチャを導入し、より大規模で安定したクラスタをサポートしています。

主な変更点は以下の通りです:

  • Core と Replicant の役割分担:Core ノードは書き込みと完全なデータ複製を担当し、Replicant ノードは読み取り専用でクライアントセッションを処理します。
  • レプリケーションログ(RLOG):Core から Replicant への非同期かつ高スループットなデータ複製を可能にします。
  • スケーラビリティ:1 クラスタあたり最大 1 億 MQTT 接続をサポートします。
EMQX_cluster

注意

厳密な上限はありませんが、EMQX オープンソース版ではクラスタサイズを3ノードに制限することを推奨します。Core タイプのノードのみを使用する場合、小規模なクラスタの方が安定性が高い傾向にあります。

このアーキテクチャを支えるために、EMQX は Erlang/OTP とルーティングおよび配信のための内部データ構造群を利用しています。Erlang/OTP の基礎およびクラスタデータ構造の節で、ランタイムの基盤とこれらの構造がクラスタ内でどのように機能するかを説明します。

Erlang/OTP の基礎

EMQX は分散型の通信システム構築を目的に設計されたランタイムおよびフレームワークであるErlang/OTP上に構築されています。Erlang では各ランタイムインスタンスをノードと呼び、<name>@<host> 形式の名前で識別します。例:emqx1@192.168.0.10

Erlang ノードは TCP 経由で接続し、軽量なメッセージパッシングで通信します。これが EMQX クラスタリングの基盤となっています。各ノードは同じクッキーを使って認証し、接続と認証が完了すると自動的に EMQX クラスタに参加できます。EMQX 5.x 以降では、ノードの役割(Core または Replicant)がデータ複製とルーティングへの参加方法を決定します。

クラスタデータ構造

分散クラスタ内で効率的にメッセージをルーティングするため、EMQX はサブスクリプションテーブル、ルーティングテーブル、トピックツリーという3つの主要な内部データ構造を使用します。これらは連携して、クライアントが多数のノードに分散していてもメッセージを正しくサブスクライバーに届けます。

サブスクリプションテーブル(パーティション化)

各 EMQX ノードはローカルのサブスクリプションテーブルを保持し、MQTT トピックとそのノードに直接接続されたクライアントをマッピングします。データはパーティション化されており、各ノードは自分のクライアントのサブスクリプションのみを保存するため、オーバーヘッドが減りスケーラビリティが向上します。

メッセージがノードにルーティングされると、そのノードはサブスクリプションテーブルを使ってローカルクライアントのうちどれにメッセージを届けるかを判断します。

例:

node1:
    topic1 -> client1, client2
    topic2 -> client3

node2:
    topic1 -> client4

この例は、同じトピック(topic1)に複数ノードでサブスクライバーが存在し、各ノードが独自にローカルマッピングを管理していることを示しています。

ルーティングテーブル(Core から複製)

ルーティングテーブルは、どのノードがどのトピックをサブスクライブしているかを追跡します。EMQX 5.x ではこのテーブルは Core ノードのみが管理・複製し、Replicant ノードは RLOG 機構を通じて読み取り専用コピーを受け取ります。

クライアントが任意のノード(通常は Replicant)でトピックをサブスクライブすると、そのサブスクリプションイベントは Core ノードに転送され、クラスタ全体のルーティングテーブルが更新・複製されます。

例:

topic1 -> node1, node2
topic2 -> node3
topic3 -> node2, node4

トピックツリー(Core から複製)

トピックツリーは階層構造で、パブリッシュされたトピックとサブスクリプションパターン(MQTT ワイルドカード+# を含む)をマッチングするために使われます。これにより EMQX は複雑なトピックフィルターを高速に解決できます。

ルーティングテーブルと同様に、トピックツリーは Core ノードによって複製され Replicant ノードと共有されます。新しいサブスクリプション(例:client1t/+/x をサブスクライブ)が来ると、トピックツリーはすべてのノードで更新されます。更新は Core ノードが処理し、その後複製されます。

トピックとサブスクリプションの例:

クライアントノードサブスクライブトピック
client1node1t/+/x, t/+/y
client2node2t/#
client3node3t/+/x, t/a

これらのサブスクリプションが設定された後、EMQX は以下のトピックツリーとルーティングテーブルを構築します:

image

メッセージ配信フロー

MQTT クライアントがメッセージをパブリッシュすると、そのクライアントが接続しているノード(Core または Replicant)はトピックツリーを使ってメッセージトピックとすべてのサブスクリプションパターンを照合します。次にルーティングテーブルを参照し、マッチするサブスクライバーがいるノードを特定してメッセージを転送します(複数ノードに転送される場合もあります)。受信した各ノードはローカルのサブスクリプションテーブルを参照し、該当するサブスクライバーにメッセージを配信します。

例として、Client 1 がトピック t/a にメッセージをパブリッシュした場合のノード間のルーティングと配信は以下の通りです:

  1. Client 1Node 1 に接続し、トピック t/a のメッセージをパブリッシュします。

  2. Node 1 はトピックツリーを確認し、t/a が既存のサブスクリプションパターン t/at/# にマッチすることを検出します。

  3. Node 1 はルーティングテーブルを参照し、

    • Node 2t/# をサブスクライブするクライアントがいる、
    • Node 3t/a をサブスクライブするクライアントがいる、

    ことを特定し、両ノードにメッセージを転送します。

  4. Node 2 はメッセージを受信し、ローカルのサブスクリプションテーブルを確認して t/# をサブスクライブするクライアントにメッセージを配信します。

  5. Node 3 はメッセージを受信し、ローカルのサブスクリプションテーブルを確認して t/a をサブスクライブするクライアントにメッセージを配信します。

  6. メッセージ配信処理が完了します。

EMQX クラスタリングの仕組みをさらに理解するには、EMQX クラスタリングの設計を参照してください。

クラスタリング機能の概要

EMQX はネイティブの Erlang 分散システムを拡張する Ekka ライブラリにより、以下の高度なクラスタリング機能を提供します。これにより自動ノード検出、動的クラスタ形成、ネットワーク分断の処理、ノードのクリーンアップなどが可能になります。

ノード検出と自動クラスタリング

EMQX は複数のノード検出メカニズムをサポートし、多様なデプロイ環境で自動的にクラスタを形成できます:

戦略説明
manualコマンドによる手動クラスタ作成
static静的ノードリストによる自動クラスタリング
DNSDNS の A レコードおよび SRV レコードによる自動クラスタリング
etcdetcd を利用した自動クラスタリング
k8sKubernetes による自動クラスタリング

詳細はクラスタの作成と管理を参照してください。

ネットワーク分断の自動修復

ネットワーク分断自動修復は、ネットワーク分断発生時に手動介入なしでブローカーが自動的に回復する機能であり、ダウンタイムが許されないミッションクリティカルな用途に有用です。

この機能は cluster.autoheal 設定で制御され、デフォルトで有効です。

bash
cluster.autoheal = true

有効時、EMQX はクラスタ内ノード間の接続状態を継続的に監視します。ネットワーク分断を検知すると、影響を受けたノードを隔離し、残りのノードで動作を継続します。分断が解消されると、ブローカーは隔離されたノードを自動的にクラスタに再統合します。

クラスタノードの自動クリーンアップ

クラスタノード自動クリーンアップ機能は、切断されたノードを設定された時間経過後に自動的にクラスタから削除します。この機能によりクラスタの効率的な運用とパフォーマンス劣化の防止が可能です。

デフォルトで有効で、cluster.autoclean 設定(デフォルト:24h)で制御されます。

bash
cluster.autoclean = 24h

ノード間セッション

EMQX はノード間のセッション永続化をサポートし、クライアントが一時的に切断してもセッションとサブスクリプションを保持します。

この機能を有効にするには:

  • MQTT 3.x クライアントclean_start = false を設定
  • MQTT 5.0 クライアントclean_start = false かつ session_expiry_interval > 0 を設定

これにより、クライアントが切断してもクライアント ID に紐づく以前のセッションデータが保持されます。再接続時に EMQX は前のセッションを再開し、切断中にキューイングされたメッセージを配信し、サブスクリプションを維持します。

ネットワーク要件

EMQX クラスタを運用するためのネットワークレイテンシは 10 ミリ秒未満が望ましいです。100 ミリ秒を超えるレイテンシの場合、クラスタは利用できません。

Core ノードは同一のプライベートネットワーク内に配置する必要があります。Mria+RLOG モードでは、Replicant ノードも同一プライベートネットワーク内に配置することを推奨します。

次のステップ:EMQX クラスタの作成

以下のセクションを続けて読み、EMQX クラスタの作成方法を学べます: