使用 Federated Exchange 讓 RabbitMQ 跨 vhost 進行訊息傳遞

想讓多個 consumer 可以收到同一個 RabbitMQ 訊息,你會怎麼做呢?我第一念頭是使用 Kafka 哈哈,如果限制只能用 RabbitMQ,我覺得 RabbitMQ Streams 應該能做到 (筆記可以參考:使用 C# 存取 RabbitMQ Streams),只是 RabbitMQ Streams 是 RabbitMQ 3.9 導入的,部份系統還在使用舊版 RabbitMQ,不一定能用,所以還有個限制是 RabbitMQ 3.8 之前版本要能用。

之前我的做法是在 message 進來的時使用 topic exchange,將 message route 至多個 queue 中:

然後再透過 shovel 將 queue 中的 message 複製到另一個 vhost 的 queue 中,細節可以參考之前筆記:RabbitMQ Shovel 將訊息同步至不同 Vhost (Cluster)

雖然使用上沒有問題,但設定上就是有些繁瑣,所以今天就來紀錄一下不同用法:使用 Federated Exchange,但說實話設定上沒有比較簡單,只是在需要較多複本的情況下,Federated Exchange 看起來比較整潔,不用多個 replication queue 跟多組 shovel 來進行同步。

做法說明:

  1. 在兩個 vhost:AB 各自建立一個 topic exchange:testex
  2. 在兩個 vhost:AB 各自建立一個 queue:testq
  3. 分別將兩個 vhost:AB 中的 testq 綁定到 testex,並且設定 routing key 為 *
  4. 設定 Federated Exchange,將 Atestex 訊息轉傳至 Btestex

基本環境說明

  • macOS Sequoia 15.1.1 (Apple M2 Pro)
  • OrbStack Version 1.8.0 (18332)
  • docker image
    • rabbitmq:3.11.9-management
    • rabbitmq:4.0.4-management
  • docker-compose.yml

  • RabbitMQ 前置作業

設定方式

  • 啟用 RabbitMQ Federation 相關套件以開啟 Federated 功能

  1. 使用 web ui

    • 設定 Federated Exchange

      1. 點選 Federation Upstreams
      2. 選擇下游所在的 Virtual host B
      3. 設定 Federation Upstream 名稱:A
      4. 設定上游 URI amqp://admin:pass.123@localhost:5672/A
      5. 設定來源 Exchange (可以使用簡單的字中比較規則): testex
      6. 設定 Queue Type 為 quorum (RabbitMQ 3 可能只能使用 HA policy)
      7. 加入 Upstream Add upstream
      • RabbitMQ 4.0.4

        1upstream4

      • RabbitMQ 3.11.9

        2upstream3

    • 設定 Federated Policy

      1. 點選 Policies
      2. 選擇下游所在的 Virtual host B
      3. 設定 Pattern 為 exchange 名稱:testex
      4. 設定 Policy 名稱:federated-exchange-policy
      5. 選擇 Apply to Exchanges
      6. 設定 Proiority:10
      7. 設定 Definition:{"federation-upstream-set":"all"}
      8. 加入 Policy Add / update policy
      • RabbitMQ 4.0.4

        3policy4

      • RabbitMQ 3.11.9

        4policy3

  2. 使用 rabbitmqctl

  • 成功設定

    1. Federation Status 會出現 running

      5status

    2. exchane 列表中上游會出現 type 為 x-federation-upstream 的 federated exchange,下游 exchange 會套上 policy 的 feature

      6exchange

    3. 上游的 exchange 詳細內容中,與 queue 的 binding 會出現 federation 的 binding

      8binding

    4. queue 列表中上游會出現 federation 的 queue

      7queue

心得

  • 版本間的 UI 有差異,造成功能的設定方式也有所不同
  • 來源 vhost 如果是 root vhost,則在設定 Federated Exchange 時,不能加上 / 否則會出現錯誤

    9error

  • 來源 vhost 如果是 root vhost 設定無法生效

    我試了 RabbitMQ 3.11.9 與 4.0.4,都無法設定 root vhost 的 Federated Exchange,我猜測可能是因為 root vhost 有特殊性,所以無法設定 Federated Exchange,所以如果要設定 Federated Exchange,建議使用非 root vhost

參考資訊

  1. Can I bind a queue from a different vhost?
  2. Federated Exchanges
  3. 使用 C# 存取 RabbitMQ Streams
  4. RabbitMQ Shovel 將訊息同步至不同 Vhost (Cluster)