3

現在調査中ですが、質問させてください。回答がない場合は、わかり次第回答を投稿します。

問題は次のとおりです。

アプリケーションは、RabbitHutch.CreateBus を呼び出して IBus/IAdvancedBus のインスタンスを作成し、RabbitMQ にメッセージを発行します。インスタンスは返されますが、IsConnected フラグは false に設定されます (つまり、接続の再試行はバックグラウンドで行われます)。アプリケーションが特定の要求を処理すると、IAdvancedBus.PublishAsync が呼び出され、バスがまだ接続されていないときにメッセージが発行されます。大きな負荷がかかると、バスが RabbitMQ に接続できなかったため、アプリケーションへのリクエストがタイムアウトしてしまいます。

リクエストの処理中に RabbitMQ への接続が失われると、同じ動作が観察されます。

質問は:

バスが切断されている間、EasyNetQ はどのようにメッセージをパブリッシュしようとしますか?

接続が確立されるまで、メッセージはメモリのキューに入れられますか? もしそうなら、制限に達した後にメッセージを破棄していますか? これは構成可能ですか?

それとも、バスが強制的に RabbitMQ に接続しようとしているのですか?

それとも、メッセージを完全にダンプしていますか?

PublisherConfirms は、動作に影響を与えるように切り替えられていますか?

4

1 に答える 1

4

上記のすべてのシナリオをテストできたわけではありませんが、RabbitMQ に公開しようとする前に、EasyNetQ がバスが接続されていることを確認しているようです。そうでない場合は、ここで説明されているように、多かれ少なかれ接続ループに入っています。 -subscriber-and-the-rabbitmq-broker

負荷が増加すると、インフラストラクチャまたは構成が壊れているため、RabbitMQ に接続することができず、接続ループが制御不能になっているように見えます。なぜタイムアウトが発生するのかはまだ特定できていませんが、複数の接続ループが同時に接続を試みると、同時実行の問題が発生する可能性があると思われます。

また、メッセージを発行できず、RabbitMQ からの確認を待機していないため、PublisherConfirms をオフにすることがまったく役立つとは思えません。

私たちのソリューション:

では、なぜこの質問に対する明確な答えが得られなかったのでしょうか。真実は、現時点で私たちが公開しようとしているメッセージは、厳密に言えばミッション クリティカルではありません。構成が間違っていると、ヘルス チェックの実行時にデプロイが失敗し、基本的にデプロイが中止されます。何らかの理由で RabbitMQ が使用できなくなった場合、これらのメッセージが公開されなくても問題ありません。

また、タイムアウトを回避するために、アプリケーションと RabbitMQ の間の回路が開いていることを検出した場合にメッセージの発行を停止する回路ブレーカーでメッセージの発行を終了しています。大まかに言えば、これは次のように機能します。

var bus = RabbitHutch.Create(...).Advanced;
var rabbitMqCircuitBreaker = new CircuitBreaker(...);
rabbitMqCircuitBreaker.AttemptCall(() => {
    if (!bus.IsConnected)
       throw new Exception(...);
    bus.Publish(...);
});

例外をスローして、IsConnected フラグが false に設定されている場合に問題があることをサーキット ブレーカーに通知していることに注意してください。構成された期間に X 回例外がスローされた場合、回路が開き、構成された時間、メッセージの発行の試行が停止されます。RabbitMQ が利用可能な場合、接続は非常に高速で 99.xxx% の時間利用可能であるため、これは許容できると考えています。また、各呼び出しの前ではなく、アプリケーションの起動時にバスが作成されることにも注意してください。したがって、有効なシナリオで実際に設定される前にフラグをチェックする可能性は非常に低くなります。

現時点では私たちのために働いています。追加情報をいただければ幸いです。

于 2015-04-22T12:43:05.510 に答える