Skip to content

トピック書き換え

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

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

TIP

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

TIP

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

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

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

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

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は設定ファイルに記述された順に書き換えルールを読み込みます。複数のルールのトピックフィルターに同時にマッチする場合は、最初にマッチしたルールでトピックを書き換えます。

ルール内の正規表現が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/2、および x/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番目のルールで再度マッチングは行われません。