私はサービス指向アーキテクチャーのメッセージキューとしてRabbitMQを使用しています。このアーキテクチャでは、多くの個別のWebサービスがRabbitMQキューにバインドされたメッセージを公開します。これらのキューは、バックグラウンド作業を実行するさまざまなコンシューマーによってサブスクライブされます。 RabbitMQのかなりバニラのユースケース。
ここで、いくつかのキューパラメータを変更したいと思います(具体的には、特定のルーティングキーを使用してキューを新しい配信不能交換にバインドしたいと思います)。私の問題は、本番システムでこの変更を行うことは、いくつかの理由で問題があるということです。
本番システムでメッセージを失うことなく、これらの新しいキューに移行するための最良の方法は何ですか?
キュー名のバージョン管理から、新しい設定で新しい仮想ホストを作成すること、すべての変更を適切に行うことまで、すべてを検討しました。
これが私が直面している問題のいくつかです:
RabbitMQキューはべき等であるため、異種のWebサービスは、キューを公開する前にキューを宣言しています(まだ存在しない場合)。キューパラメータを変更すると(ただし、同じルーティングキーを維持すると)、キュー宣言は失敗し、RabbitMQはチャネルを閉じます。
キューを変更するときにメッセージが失われないようにしたいと思います(ここでは、メッセージを保存してから新しいキューに再公開する排他的コンシューマーをサブスクライブすることを計画しています)。
異種の発行者と消費者ベースの間の一般的な調整(または、さらに良いことに、それらを調整する必要を回避する方法)。
クライアントが手動でバインディングを変更しない限り、キューバインディングは、クライアントに影響を与えることなく、実行時に追加および削除できます。したがって、バインディングについてのみ質問する場合は、CLIまたはWeb管理パネルを使用してバインディングを変更し、以下に記載されている内容をスキップしてください。
特に異種環境で、特に複数のアプリケーションが独自の方法で(特定の設定で)同じエンティティを宣言しようとする場合、互換性のない変更を行うことは一般的な問題です。複数のアプリケーションで同時にキュー宣言を変更する簡単な方法はありません。それは、作業プロセス全体の編成方法、アプリの重要度、インフラストラクチャなどに大きく依存します。
速くて汚い方法:
パブリッシャーはキューの宣言とバインディングを扱いませんが(少なくともそうすべきではありません)、コンシューマーに焦点を合わせることができます。 try-exceptブロックでのキュー宣言のラップは、高速でダーティな選択である可能性があります。また、ほとんどのプロジェクトは、多数のプロジェクトでも小さなダウンタイムに耐えることができるため、1つのシェルでrabbitmqユーザーをブロックし、必要に応じてキューを変更し(新しいプロジェクトを作成して、古いものではなく消費者に使用させる)、ユーザーのブロックを解除して、消費者を以前(あなたの労働者は監督者または監視下にありますよね?)次に、メッセージを古いキューから新しいキューに手動で移行します。
高速で安全なソリューション:
これは少し注意が必要で、単一の仮想ホスト内でメッセージを1つのキューから別のキューに移行する方法をハックに基づいています。ソリューション全体は単一の仮想ホスト内で機能しますが、変更するキューごとに追加のキューが必要です。ソースキューに Dead Letter Exchanges を設定し、期限切れのメッセージを新しいターゲットキューにルーティングするように指定します。次に、 キューごとのメッセージTTL をソースキューに適用し、x-message-ttl=0
を設定します(最小値にするには、 キューイングなし 即時配信に関する注意を参照してください)。両方のアクションは、CLIまたは管理パネルを介して実行でき、すでに宣言されているキューで実行できます。このようにして、パブリッシャーは通常どおりメッセージを公開でき、古いコンシューマーでも初めて期待どおりに動作できますが、並行して、新しいコンシューマーは、手動またはその他の方法で新しい引数で事前に宣言できる新しいキューから消費できます。
メッセージ数が多く、メッセージフローが大きいキューでは、特にサーバーがほとんどすべてのリソースを使用している場合、フロー制御の制限を満たすリスクがあることに注意してください。
はるかに複雑ですがより安全なアプローチ(メッセージ全体のワークフローロジックが変更された場合):
アプリケーションに必要なすべての変更を加え、既存のコードベースと並行して新しいコードベースを実行しますが、異なるRabbitMQ仮想ホストで実行します(または別のサーバーを使用する場合でも、アプリケーションの負荷とハードウェアによって異なります)。実際には、同じ仮想ホストで実行でき、交換とキューの名前を変更することは可能かもしれませんが、書面でも音が良くなく、臭いもします。新しいアプリをセットアップしたら、古いアプリに切り替えて、古いキューから新しいキューへのメッセージの移行を実行します(または、古いシステムでキューを空にします)。最小限のダウンタイムでシームレスな移行を保証します。展開を自動化すると、プロセス全体にそれほど手間がかかりません。
追伸:上記のいずれの場合でも、可能であれば、古いコンシューマーにキューを空にして、メッセージを手動で移行する必要がないようにします。
更新:
Shovelプラグイン 、特に Dynamic Shovels は、異なるvhostとサーバー間であっても、交換とキューの間でメッセージを移動するのに非常に便利です。これは、キュー/エクスチェンジ間でメッセージを移行するための最も高速で安全な方法です。