Une fois que le consommateur a reçu un message, le consommateur/travailleur effectue certaines validations, puis appelle le service Web. Dans cette phase, si une erreur se produit ou si la validation échoue, nous voulons que le message soit remis dans la file d'attente à partir de laquelle il a été consommé à l'origine.
J'ai lu la documentation de RabbitMQ. Mais je suis confus quant aux différences entre les méthodes de rejet, de nack et d'annulation.
Réponse courte:
Pour remettre en file d'attente un message spécifique, vous pouvez choisir à la fois basic.reject
Ou basic.nack
Avec l'indicateur multiple
défini sur false.
L'appel de basic.consume
Peut également entraîner la redistribution des messages si vous utilisez l'accusé de réception de message et qu'il y a un message non acquitté sur le consommateur à un moment précis et qu'il quitte sans l'acquitter.
basic.recover
Retransmettra tous les messages non acquittés sur un canal spécifique.
Réponse longue:
basic.reject
et basic.nack
les deux ont le même objectif - supprimer ou remettre en file d'attente un message qui ne peut pas être géré par un consommateur spécifique (à la date indiquée) moment, sous certaines conditions ou pas du tout). La principale différence entre eux est que basic.nack
Prend en charge le traitement des messages en masse, contrairement à basic.reject
.
Cette différence décrite dans Remerciements négatifs article sur le site Web officiel de RabbitMQ:
La spécification AMQP définit la méthode
basic.reject
Qui permet aux clients de rejeter les messages individuels remis, en demandant au courtier de les supprimer ou de les remettre en file d'attente. Malheureusement,basic.reject
Ne prend pas en charge la reconnaissance négative des messages en masse.Pour résoudre ce problème, RabbitMQ prend en charge la méthode
basic.nack
Qui fournit toutes les fonctionnalités debasic.reject
Tandis que permet également un traitement en masse des messages .Pour rejeter les messages en bloc, les clients définissent l'indicateur
multiple
de la méthodebasic.nack
Surtrue
. Le courtier rejettera ensuite tous les messages non acquittés et remis jusqu'au message inclus dans le champdelivery_tag
De la méthodebasic.nack
. À cet égard,basic.nack
complète la sémantique d'accusé de réception en masse debasic.ack
.
Notez que la méthode basic.nack
Est une extension spécifique à RabbitMQ tandis que la méthode basic.reject
Fait partie de la spécification AMQP 0.9.1.
Quant à la méthode basic.cancel
, elle avait l'habitude d'aviser le serveur que le client arrêtait de consommer des messages. Notez que ce client peut recevoir un nombre arbitraire de messages entre la méthode basic.cancel
Et l'envoi de la réponse cancel-ok
. Si l'accusé de réception de message est utilisé par le client et qu'il contient des messages non acquittés, ils seront replacés dans la file d'attente à partir de laquelle ils ont été consommés à l'origine.
basic.recover
a quelques limitations dans RabbitMQ: il - basic.recover avec requeue = false - basic.recover synchronicity
En plus des errata, selon les spécifications de RabbitMQbasic.recover
A un support partiel (La récupération avec requeue = false n'est pas supportée.)
Remarque sur basic.consume
:
Lorsque basic.consume
a démarré sans acquittement automatique (noack=false
) Et qu'il y a des messages en attente des messages non acquittés, puis lorsque le consommateur est annulé (meurt, erreur fatale, exception , peu importe) que les messages en attente seront redistribués. Techniquement, les messages en attente ne seront pas traités (même les lettres mortes) jusqu'à ce que le consommateur les libère (ack/nack/rejet/récupération). Ce n'est qu'après cela qu'ils seront traités (par exemple, en lettre morte).
Par exemple, supposons que nous publions à l'origine 5 messages consécutifs:
Queue(main) (tail) { [4] [3] [2] [1] [0] } (head)
Et puis consommer 3 d'entre eux, mais pas les acquitter, puis annuler le consommateur. Nous aurons cette situation:
Queue(main) (tail) { [4] [3] [2*] [1*] [0*] } (head)
où star (*
) note que l'indicateur redelivered
est défini sur true
.
Supposons que nous ayons une situation avec un ensemble d'échange de lettres mortes et une file d'attente pour les messages de lettres mortes
Exchange(e-main) Exchange(e-dead)
Queue(main){x-dead-letter-exchange: "e-dead"} Queue(dead)
Et supposons que nous publions 5 messages avec la propriété expire
définie sur 5000
(5 sec):
Queue(main) (tail) { [4] [3] [2] [1] [0] } (head)
Queue(dead) (tail) { }(head)
puis nous consommons 3 messages de la file d'attente main
et les maintenons pendant 10 secondes:
Queue(main) (tail) { [2!] [1!] [0!] } (head)
Queue(dead) (tail) { [4*] [3*] } (head)
où le point d'exclamation (!
) représente le message non empilé. Ces messages ne peuvent être livrés à aucun consommateur et ils ne peuvent normalement pas être affichés dans le panneau de gestion. Mais annulons le consommateur, rappelez-vous, qu'il contient toujours 3 messages non confirmés:
Queue(main) (tail) { } (head)
Queue(dead) (tail) { [2*] [1*] [0*] [4*] [3*] } (head)
Alors maintenant que 3 messages qui étaient dans la tête sont remis dans la file d'attente d'origine, mais comme ils ont par message TTL défini, ils sont en lettres mortes à la fin de la file d'attente des lettres mortes (bien sûr , via échange de lettres mortes).
P.S.:
Consommer un message aka écouter un nouveau est en quelque sorte différent de l'accès direct à la file d'attente (obtenir un ou plusieurs messages sans prendre soin des autres). Voir basic.get
description de la méthode pour en savoir plus.