17

このpythonバインディングでRabbitMQを試しています。

私が気づいたことの 1 つは、(クラッシュしたプログラムをエミュレートして) コンシューマーを不当に殺すと、サーバーはこのコンシューマーがまだ長い間存在していると見なすことです。この結果、他のすべてのメッセージは無視されます。

たとえば、コンシューマーを 1 回強制終了して再接続すると、1/2 のメッセージが無視されます。別のコンシューマーを強制終了すると、メッセージの 2/3 が無視されます。3 番目を殺すと、3/4 メッセージは無視されます。

確認応答をオンにしてみましたが、効果がないようです。私が見つけた唯一の解決策は、サーバーを手動で停止してリセットすることです。

より良い方法はありますか?

このシナリオを再現する方法

  • rabbitmq を実行します。

  • このライブラリを解凍します。

  • コンシューマーとパブリッシャーはこちらからダウンロードしてください。amqp_consumer.py を 2 回実行します。amqp_publisher.py を実行していくつかのデータを入力し、期待どおりに動作することを確認します。メッセージはラウンドロビン方式で受信されます。

  • kill -9 またはタスク マネージャを使用して、コンシューマ プロセスの 1 つを強制終了します。

  • メッセージを公開すると、メッセージの 50% が失われます。

4

3 に答える 3

5

RabbitMQ には、メッセージが処理されたというクライアントからの確認応答にタイムアウトがありません。この投稿を参照してください(スレッド全体が興味深いかもしれません)。投稿からのいくつかの顕著な点:

サブスクリプションと「プル」の AMQP ack モデルは同じです。どちらの場合も、メッセージはサーバーに保持されますが、確認応答される (および削除される) か、応答拒否される (basic.reject を使用。ただし、RabbitMQ はそれを実装していません)、または channel/接続が閉じられます (その時点で、メッセージは他のコンシューマーが利用できるようになります)。

そして(私の強調)

ack の待機にタイムアウトはありません。通常、これは問題ではありません。 なぜなら、ACK が見つからないという一般的なケース (ネットワークまたはクライアントの障害) では、接続が切断される(したがって、上記の動作が引き起こされる) ためです。それでも、タイムアウトは、たとえば、生きているが応答しないコンシューマーに対処するのに役立ちます。それは以前に議論に出てきました。そのような機能を必要とする具体的なユースケースはありますか?

この問題が発生している可能性があります。クライアント プル モデルでは、サーバーが切断された接続を検出するのが (生きているが応答しないコンシューマーとは対照的に) 難しいためです。

更新: Linux では、SIGTERM および/または SIGKILL および/または SIGINT のシグナル ハンドラーをアタッチし、うまくいけば、クライアントから正常な方法で接続を閉じることができます。Windows では、タスク マネージャーを閉じると Win32 TerminateProcessAPI が呼び出されると思います。これについて MSDN は次のように述べています。

プロセスが によって終了された場合、プロセス TerminateProcessのすべてのスレッドはすぐに終了し、追加のコードを実行する機会はありません。これは、スレッドが終了ハンドラ ブロックでコードを実行しないことを意味します。さらに、アタッチされた DLL には、プロセスがデタッチ中であることが通知されません。

これは、終了を見つけて整然と閉鎖することが難しい可能性があることを意味します。

ACK タイムアウトの独自のユースケースを使用して、RabbitMQ リストを追求する価値があるかもしれません。

于 2009-09-05T22:46:53.030 に答える
2

宣言したコンポーネントについて、もう少し具体的に説明してください。通常は (クライアントの実装とは無関係に) プロパティを持つキュー

  • 排他的で
  • 自動削除

宣言しているクライアントとブローカーの間の接続が切断されるとすぐに削除する必要があります。ただし、これは共有キューでは役に立ちません。モデル化しようとしているものを正確に少し詳しく説明してください。

于 2009-09-04T12:37:25.310 に答える