第 10 章

內建動作與訊息轉發

規則 SQL 算出結果之後,動作就是「把結果送到哪」。這章深入 Republish 與 Console Output 兩種內建動作,也看設定檔如何宣告動作。

為什麼要學這個

第 9 章你寫得出規則 SQL,但規則引擎真正的價值在「命中之後真的做出某件事」。只把資料卡在 SQL 輸出裡,等於沒用;動作(action)就是把規則處理完的結果轉成實際行為——轉發到另一個 topic、印到 log 供除錯、或送進外部資料系統。

這章聚焦 EMQX 5.8.9 的內建動作,尤其是 republish 與 console。「送給外部系統」的動作(Webhook、Kafka、資料庫)依賴 Connector/Sink,留到第 11 章詳談。

核心概念

一個規則可以在 actions 裡配置一個或多個動作;規則會依序執行。動作要用的資料,來自 SQL 執行結果——你可以用 ${欄位名} 這種佔位語法,把規則輸出的欄位塞進動作參數(例如把 SQL 挑出的 payload 或 clientid 放進 republish 的 topic 或 payload)。

EMQX 5.8.9 的三種內建動作:

  • Message Republishing(轉發):把規則結果重新發布到 MQTT 主題。
  • Console Output(主控台輸出):把結果印到主控台或 log,主要用於除錯。
  • Forwarding to Sinks(送進外部系統):把結果交給 Sink(第 11 章)。

建立規則時,在「Add Action」下拉選單挑動作即可;也可以用 emqx.conf 設定檔宣告同樣的規則與動作。

名詞對照

英文中文一句話
Action動作規則命中後執行的輸出行為
Republish轉發把規則結果重新發布到另一 MQTT topic
Console Output主控台輸出把結果印到主控台/log,供除錯
Forwarding轉送把結果送進 Sink(外部系統)
${key}佔位符在動作參數中引用規則輸出的欄位

動手做

  1. 建立規則

    在 Dashboard 選 Integration → Rules → Create,填規則名,SQL 輸入 SELECT * FROM "t/#"。

  2. 加入 Republish 動作

    按右側 Add Action,Action 下拉選 Republish;Target Topic 填 a/1,QoS 設 0,Retain 設 false。

  3. 設定 Payload 佔位符

    在 Payload 欄位輸入 ${payload},讓轉發訊息沿用原訊息內容;需要時也能用 ${clientid} 等欄位拼出自訂 payload。

  4. 處理 MQTT 5.0 屬性(選擇性)

    展開「MQTT 5.0 Message Properties」開關,可設定 Payload Format Indicator、Message Expiry Interval、Content Type、Response Topic、Correlation Data 等屬性。

  5. 建立並驗證

    按 Create 完成。訂閱 a/1,向 t/1 發布訊息,應收到轉發結果;也可用 Test the Rule 直接模擬。

Republish 與 Console Output

Republish 是常用的「資料轉型+改道」動作。官方範例把 t/#a/1:轉發不會攔截原始訊息,原本訂閱 t/1 的 client 仍照常收到,只是多出一份 a/1。加上Direct Dispatch 開關可讓訊息直接送給訂閱者,避免再觸發其他規則而陷入遞迴。

Republish 的常見參數:

參數說明
Topic轉發目標主題,可用 ${…} 組出動態主題
QoS轉發訊息的 QoS 等級
Retain是否作為 retained 訊息發布
Payload轉發 payload 模板(常見 ${payload})
MQTT 5.0 屬性選用:Payload Format、Expiry、Content Type、Response Topic、Correlation Data
Direct Dispatch直接送達訂閱者,避免規則遞迴

Console Output 動作只把規則結果印到主控台或 log(格式為 [rule action] 規則ID + Action Data + Envs)。它只該用在除錯:EMQX 以 foreground(Docker 預設)啟動時輸出到主控台;以 systemd 啟動時會進 journal,可用 journalctl 檢視。官方明確警告:正式環境用 console 可能拖慢效能。

用設定檔宣告動作與 ${var}

規則與動作也能寫進 emqx.conf,在 EMQX 啟動前就生效。在 rule_engine 命名空間下用 rules.<id> 定義,例如:

rule_engine {
  rules.my_republish_rule {
    sql = "SELECT qos, payload.x as y FROM \"t/a\""
    actions = [
      {
        function = republish
        args = {
          topic = "t/b"
          qos = "${qos}"
          payload = "y: ${y}"
        }
      }
    ]
  }
}

這裡 ${qos} 與 ${y} 是引用 SQL 輸出欄位的佔位符。例如送進 t/a 一則 {"x":1},規則先挑出 qos 並把 payload 的 x 改名 y,最後 republish 到 t/b,payload 是 y: 1。

若要在規則裡指定一個外部整合 Sink 作為動作,則在 actions 陣列直接填 bridge ID(如 "mqtt:my_egress_mqtt_bridge");若是 console 動作,例如 actions = [{function = console}],會把規則輸出印到主控台。事件型規則(如 client 上線 $events/client_connected)一樣能用設定檔宣告。

故障排除

  • Republish 沒收到轉發訊息:確認規則已啟用、SQL 的 FROM pattern 與發布主題相符、動作已儲存、目標 topic/QoS 設定無誤;可先用「Test the Rule」模擬。
  • Console 沒看到輸出:EMQX 以 background 啟動時輸出進 journal,可用 journalctl 檢視;若以 Docker foreground 執行則看主控台。
  • Payload 不是預期的格式:轉發 payload 是字串模板,你必須打出想要的樣式(例如 ${payload} 或混合文字 + ${欄位})。
  • 規則自我觸發、造成遞迴:Republish 的目標 topic 若又符合同一規則的 FROM,會無限次再觸發。可用 Direct Dispatch 或改目標 topic 避開。

常見問題

Republish 會擋掉原本的訊息嗎

不會。Republish 只是多送一份到目標主題;原本發布到 t/1 的訊息仍會照常送給訂閱 t/1 的 client。

Console Output 適合 production 嗎

不適合。官方把它標為除錯用途,大量輸出會拖慢效能;production 建議用 republish 或送往 Sink。

能同時設定多個動作嗎

可以。規則的 actions 是可陣列,可在 UI 連續加入多個動作,設定檔裡也以陣列列出;規則依序執行。

什麼時候用 republish、什麼時候用 Sink

只是把資料改主題轉發,用 republish;要送往外部系統(資料庫、HTTP、Kafka、MQTT 遠端 broker),就用 Forwarding to Sinks(Sink)。

官方來源