內建動作與訊息轉發
規則 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} | 佔位符 | 在動作參數中引用規則輸出的欄位 |
動手做
建立規則
在 Dashboard 選 Integration → Rules → Create,填規則名,SQL 輸入
SELECT * FROM "t/#"。加入 Republish 動作
按右側 Add Action,Action 下拉選 Republish;Target Topic 填
a/1,QoS 設0,Retain 設false。設定 Payload 佔位符
在 Payload 欄位輸入
${payload},讓轉發訊息沿用原訊息內容;需要時也能用${clientid}等欄位拼出自訂 payload。處理 MQTT 5.0 屬性(選擇性)
展開「MQTT 5.0 Message Properties」開關,可設定 Payload Format Indicator、Message Expiry Interval、Content Type、Response Topic、Correlation Data 等屬性。
建立並驗證
按 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)。