Skip to content

EMQX クラスタリング

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

注意

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

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

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

章のプレビュー

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

高可用な MQTT プラットフォームの構築や本番規模の準備に役立つガイドです。

なぜ 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 はベンチマークテストで 1,000 万同時接続を達成しましたが、これには大幅なチューニングと高性能ハードウェアが必要でした。詳細はパフォーマンスレポートを参照してください。

EMQX 5.0 以降:Mria + RLOG

バージョン 5.0 からは、新しい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 クラスタリングの基礎となります。各ノードは認証のために同じクッキーを使用し、接続と認証が完了すると自動的に 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 ノードと共有されます。新しいサブスクリプション(例: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 が提供する自動クラスタリング

詳細はクラスタの作成と管理をご覧ください。

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

ネットワークパーティション自動修復は、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 クラスタの作成方法を学べます。