web-dev-qa-db-ja.com

RabbitMQでメッセージをリキューする方法

コンシューマーがメッセージを取得した後、コンシューマー/ワーカーはいくつかの検証を行ってからWebサービスを呼び出します。このフェーズでは、エラーが発生した場合や検証が失敗した場合、最初に消費されたキューにメッセージを戻す必要があります。

RabbitMQのドキュメントを読みました。しかし、リジェクト、ナック、キャンセルの各メソッドの違いについて混乱しています。

27
yunus kula

短い答え:

特定のメッセージを再キューするには、multipleフラグをfalseに設定して、basic.rejectまたはbasic.nackの両方を選択できます。

basic.consume呼び出しは、メッセージ確認応答を使用しており、特定の時間にコンシューマーに未確認のメッセージがあり、コンシューマーが確認応答せずに終了した場合、メッセージが再配信されることもあります。

basic.recoverは、特定のチャネルですべての未確認メッセージを再配信します。

長答:

basic.reject および basic.nack は両方とも同じ目的に使用されます-特定のコンシューマーが処理できないメッセージをドロップまたはリキューします(特定の時点で、特定の条件下またはまったく)。それらの主な違いは、basic.nackはバルクメッセージ処理をサポートするのに対し、basic.rejectはサポートしないことです。

負の謝辞 公式RabbitMQ Webサイトの記事で説明されているこの違い:

AMQP仕様では、クライアントが個々の配信されたメッセージを拒否し、ブローカーにメッセージを破棄するか、キューに再配置するよう指示するbasic.rejectメソッドを定義しています。残念ながら、basic.rejectは、否定的なメッセージの一括確認をサポートしていません。

これを解決するために、RabbitMQはbasic.nackのすべての機能を提供するbasic.rejectメソッドをサポートしていますが、メッセージの一括処理も可能です

メッセージを一括して拒否するには、クライアントはbasic.nackメソッドのmultipleフラグをtrueに設定します。その後、ブローカは、delivery_tagメソッドのbasic.nackフィールドで指定されたメッセージを含む、確認されていない配信済みメッセージをすべて拒否します。この点で、 basic.nackbasic.ack の一括確認応答セマンティクスを補完します。

basic.nackメソッドはRabbitMQ固有の拡張機能であり、basic.rejectメソッドはAMQP 0.9.1仕様の一部であることに注意してください。

basic.cancel メソッドについては、クライアントがメッセージの消費を停止することをサーバーに通知するために使用されていました。クライアントはbasic.cancelメソッドとcancel-ok応答の受信の間にある任意のメッセージ番号を受信する場合があることに注意してください。メッセージ確認がクライアントによって使用され、確認されていないメッセージがある場合、それらは最初に消費されたキューに戻されます。

basic.recover RabbitMQにはいくつかの制限があります:it- basic.recover with requeue = false - basic.recover synchronicity

正誤表に加えて、 RabbitMQ仕様に準拠basic.recoverには部分的なサポートがあります(requeue = falseによるリカバリはサポートされていません)。

basic.consumeに関する注意

basic.consume auto-ack(no­ack=false)なしで開始され、いくつかの保留中のメッセージが確認されていない場合、コンシューマがキャンセルされる(ダイ、致命的なエラー、例外など) )保留中のメッセージは再配信されます。技術的には、保留中のメッセージは、消費者がそれらを解放する(ack/nack/reject/recover)まで処理されません(配信不能であっても)。その後のみ処理されます(例:デッドレター)。

たとえば、元々5つのメッセージを連続して投稿するとします。

Queue(main) (tail) { [4] [3] [2] [1] [0] } (head)

そして、それらのうち3つを消費しますが、それらを確認してから、消費者をキャンセルします。この状況になります。

Queue(main) (tail) { [4] [3] [2*] [1*] [0*] } (head)

ここで、スター(*)は、redeliveredフラグがtrueに設定されていることに注意します。

送達不能の交換セットと送達不能メッセージのキューの状況があると仮定します

Exchange(e-main)                                   Exchange(e-dead) 
  Queue(main){x-dead-letter-exchange: "e-dead"}       Queue(dead) 

そして、expireプロパティが5000(5秒)に設定された5つのメッセージを投稿すると仮定します。

Queue(main) (tail) { [4] [3] [2] [1] [0] } (head)
Queue(dead) (tail) { }(head)

次に、mainキューから3つのメッセージを消費し、10秒間保持します。

Queue(main) (tail) { [2!] [1!] [0!] } (head)
Queue(dead) (tail) { [4*] [3*] } (head)

感嘆符(!)は、未確認のメッセージを表します。そのようなメッセージはどのコンシューマにも配信できず、通常は管理パネルで表示できません。ただし、消費者をキャンセルして、まだ3つの未確認メッセージを保持していることを思い出してください。

Queue(main) (tail) { } (head)
Queue(dead) (tail) { [2*] [1*] [0*] [4*] [3*] } (head)

そのため、先頭にあった3つのメッセージは元のキューに戻されましたが、メッセージごとにTTLが設定されているため、配信不能キューの末尾に配信されます( 、デッドレター交換経由)。

P.S.:

新しいメッセージをリッスンしているメッセージを消費することは、直接キューアクセス(他のメッセージを処理せずに1つ以上のメッセージを取得する)とは多少異なります。詳細については、 basic.get メソッドの説明を参照してください。

53
pinepain