Skip to content

トピック書き換え

多くのIoTデバイスは再設定やアップグレードに対応していないため、サブスクライブするトピックを変更することが困難です。この問題を解決するために、EMQXはトピック書き換え機能を導入しました。関連するルールを設定することで、EMQXは新しいメッセージを送信するクライアントや新しいトピックをサブスクライブするクライアントのサブスクライブトピックを自動的に書き換えます。

このトピック書き換え機能は、保持メッセージ遅延パブリッシュ機能と組み合わせて使用できます。例えば、ユーザーが遅延パブリッシュを利用したい場合、トピック書き換えを使ってメッセージを必要なトピックにリダイレクトすることが可能です。

TIP

トピック書き換えは、書き換え前に認可チェックが実行されます。

TIP

トピック書き換えは、共有サブスクリプショントピックのクライアントのサブスクライブ/サブスクライブ解除時には、実際のトピック部分にのみ適用されます。つまり、共有サブスクリプショントピックのプレフィックス $share/<group-name>/$queue を除いた部分にのみ影響します。

例えば、クライアントが $share/group/t/1$queue/t/2 のような共有サブスクリプショントピックフィルターをサブスクライブ/サブスクライブ解除する場合、EMQXは $share/group/$queue/ を無視して、t/1t/2 のみをマッチングおよび書き換えの対象とします。

共有サブスクリプションや $queue についての詳細は、共有サブスクリプションをご参照ください。

トピック書き換えルールの設定

EMQXのトピック書き換えルールは設定が必要です。複数のトピック書き換えルールを追加できます。ルール数に制限はありませんが、トピックを含むすべてのMQTTメッセージは再度書き換えルールにマッチングされるため、高スループット環境ではルール数に比例してパフォーマンスのオーバーヘッドが発生します。そのため、この機能は慎重に使用してください。

各トピックの書き換えルールのフォーマットは以下の通りです。

bash
rewrite = [
  {
    action:       "all"
    source_topic: "x/#"
    dest_topic:   "x/y/z/$1"
    re:           "^x/y/(.+)$"
  }
]

各書き換えルールはフィルターと正規表現で構成されます。

書き換えルールは publishsubscribeall の3種類に分かれています。publish ルールはPUBLISHメッセージのトピックにマッチし、subscribe ルールはSUBSCRIBEおよびUNSUBSCRIBEメッセージのトピックにマッチします。all ルールはPUBLISH、SUBSCRIBE、UNSUBSCRIBEのすべてのメッセージに対して有効です。

トピック書き換えが有効な状態で、PUBLISHメッセージなどトピックを含むMQTTパケットを受信すると、EMQXはパケット内のトピックを使って設定ファイル内のルールのトピックフィルター部分に順番にマッチングを試みます。マッチングに成功すると、正規表現でトピック内の情報を抽出し、元のトピックを置き換えて新しいトピックを生成します。

置き換え先の式では、$N 形式の変数を使って正規表現で抽出した要素を参照できます。$N の値は正規表現で抽出されたN番目の要素を表します。例えば、$1 は正規表現で抽出された最初の要素です。

また、置き換え先の式では ${clientid} を使ってクライアントIDを、${username} を使ってクライアントのユーザー名を表すことも可能です。

なお、EMQXは設定ファイルに記載された順に書き換えルールを読み込みます。トピックが複数の書き換えルールのトピックフィルターに同時にマッチする場合、EMQXは最初にマッチしたルールのみを使ってトピックを書き換えます。

ルール内の正規表現がMQTTパケットのトピックにマッチしない場合、書き換えは失敗し、他のルールによる書き換えは行われません。そのため、MQTTパケットのトピックとトピック書き換えルールは慎重に設計する必要があります。

以下のトピック書き換えルールが設定ファイルに追加されているとします。

bash
rewrite = [
  {
    action:       "all"
    source_topic: "y/+/z/#"
    dest_topic:   "y/z/$2"
    re:           "^y/(.+)/z/(.+)$"
  }
  {
    action:       "all"
    source_topic: "x/#"
    dest_topic:   "z/y/x/$1"
    re:           "^x/y/(.+)$"
  }
  {
    action:       "all"
    source_topic: "x/y/+"
    dest_topic:   "z/y/$1"
    re:           "^x/y/(\d+)$"
  }
]

この状態で、以下の5つのトピックにサブスクライブするとします:y/a/z/by/defx/1/2x/y/2x/y/z

  • y/def はどのトピックフィルターにもマッチしないため、トピック書き換えは行われず、そのまま y/def トピックにサブスクライブします。
  • y/a/z/by/+/z/# トピックフィルターにマッチします。EMQXは最初のルールを適用し、正規表現で [a、b] の要素を抽出し、2番目の要素を y/z/$2 に代入して、実際には y/z/b トピックにサブスクライブします。
  • x/1/2x/# トピックフィルターにマッチします。EMQXは2番目のルールを適用しますが、正規表現にマッチしないためトピック書き換えは行われず、実際には x/1/2 トピックにサブスクライブします。
  • x/y/2x/#x/y/+ の2つのトピックフィルターに同時にマッチします。EMQXは設定を上から順に読み込むため、3番目のルールを優先して適用します。正規表現による置換により、実際には z/y/2 トピックにサブスクライブします。
  • x/y/zx/#x/y/+ の2つのトピックフィルターに同時にマッチします。EMQXは設定を上から順に読み込むため、3番目のルールを優先して適用しますが、正規表現にマッチしないためトピック書き換えは行われず、実際には x/y/z トピックにサブスクライブします。なお、3番目のルールの正規表現マッチが失敗しても、2番目のルールで再度マッチングは行われません。