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 から EMQX は新しいMria クラスターアーキテクチャを導入し、より大規模かつ安定したクラスタをサポートしています。

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

  • Core と Replicant の役割分担:Core ノードは書き込みと完全なデータ複製を担当し、Replicant ノードは読み取り専用でクライアントセッションを処理します。
  • レプリケーションログ(RLOG):Core から Replicant への非同期かつ高スループットなデータ複製を可能にします。
  • スケーラビリティ:クラスタあたり最大 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 クラスタリングの基盤です。各ノードは同じ cookie を用いて認証し、接続が確立・認証されると自動的に 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 ワイルドカードの + と # を含む)を照合するために使われます。これにより複雑なトピックフィルターを高速に解決可能です。

ルーティングテーブル同様、トピックツリーは Core ノードで複製され Replicant ノードと共有されます。新しいサブスクリプション(例:client1 が t/+/x をサブスクライブ)を受けると、トピックツリーは全ノードで更新されます。更新は Core ノードが処理し複製します。

サブスクリプション例:

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

これらのサブスクリプションに基づき、EMQX は以下のトピックツリーとルーティングテーブルを構築します。

image

メッセージ配信フロー ​

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

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

  1. クライアント1 は ノード1 に接続し、トピック t/a でメッセージをパブリッシュ。

  2. ノード1 はトピックツリーを参照し、t/a がサブスクリプションパターン t/a と t/# にマッチすることを確認。

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

    • ノード2 が t/# にサブスクライブしている、
    • ノード3 が t/a にサブスクライブしている、

    ことを確認し、メッセージを ノード2 と ノード3 に転送。

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

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

  6. メッセージ配信が完了。

EMQX クラスタリングの動作をより深く理解するには、EMQX クラスタリングの設計もご参照ください。

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

EMQX は、ネイティブな Erlang 分散システムを拡張したEkkaライブラリを活用し、高度なクラスタリング機能を提供しています。この抽象化により、ノードの自動検出、動的クラスタ形成、ネットワークパーティションの処理、ノードのクリーンアップなどの主要機能が実現されています。

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

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

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

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

ネットワークパーティションの自動修復 ​

ネットワークパーティション自動修復は、EMQX がネットワーク分断から手動介入なしに自動復旧する機能であり、ダウンタイムが許されないミッションクリティカルな用途に有効です。

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

bash
cluster.autoheal = true

有効時、EMQX はクラスタ内ノード間の接続性を継続監視し、ネットワークパーティションを検出すると影響を受けたノードを隔離し、残りのノードで稼働を継続します。パーティションが解消されると、隔離されたノードを自動的にクラスタに再統合します。

パーティション検出・復旧時のログメッセージやアラームについては、Mria ログとアラームを参照してください。

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

クラスタノード自動クリーンアップ機能は、切断されたノードを設定された時間経過後に自動的にクラスタから削除します。この機能によりクラスタの効率的な稼働が維持され、時間経過によるパフォーマンス低下を防止します。

デフォルトで有効で、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 クラスタの作成方法を学べます: