Comment remettre en file d'attente un message à l'arrière d'une file d'attente Rabbit MQ via Spring

Nov 20 2020

J'écris un SpringBoot RabbitMQ Consumer et j'ai besoin de remettre occasionnellement un message en file d'attente à l'arrière de la file d'attente

Je pensais que c'était ainsi que l'accusé de réception négatif fonctionnait, mais basicReject(deliveryTag, true)remet simplement le message aussi près que possible de sa position d'origine dans la file d'attente, ce qui dans mon cas un à la fois est de retour au FRONT de la file d'attente.

Ma première pensée a été d'utiliser une file d'attente de lettres mortes renvoyées dans la file d'attente de messages à un certain intervalle de temps ( similaire à l'approche mentionnée dans cette réponse ), mais je préférerais ne pas créer une file d'attente supplémentaire s'il existe un moyen de simplement remettre en file d'attente le BACK de la file d'attente initiale

Ma structure ci-dessous consomme simplement le message et ne parvient pas à le rajouter à la file d'attente.

Comment cela peut-il être accompli sans DLQ?

@ServiceActivator(inputChannel = "amqpInputChannel")
    public void handle(@Payload String message,
                       @Header(AmqpHeaders.CHANNEL) Channel channel,
                       @Header(AmqpHeaders.DELIVERY_TAG) Long deliveryTag){

    try{

        methodThatThrowsRequeueError();
        methodThatThrowsMoveToErrorQueueError();

    } catch (RequeueError re) {

        channel.basicAck(deliveryTag, false);
        sendMessageToBackOfQueue(message);
        return;

    } catch (MoveToErrorQueueError me) {
        //Structured the same as sendMessageToBackOfQueue, works fine
        moveMessageToErrorQueue(message);
    }
    
    channel.basicAck(deliveryTag, false);
}

private void sendMessageToBackOfQueue(String message) {
        try {
            rabbitTemplate.convertAndSend(
                exchangeName,
                routingKeyRequeueMessage,
                message,
                message -> {
                    message.getMessageProperties().setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
                    return message;
                }
            );
        } catch (AmqpException amqpEx) {
            //error handling which is not triggered...
        }
    }

Réponses

DapperDan Nov 25 2020 at 01:48

TL; DR : Il n'y a aucun moyen que j'ai trouvé pour renvoyer un message d'un service d'écoute dans la file d'attente d'origine sans intermédiaire.

Il existe plusieurs options qui tournent autour des files d'attente de lettres mortes / des échanges de lettres mortes, mais une solution non DLQ / DLX que nous avons trouvée était un échange chronométré, un psuedo DLX si vous voulez. Essentiellement:

Le message entre dans MessageExchange (MsgX), qui se propage à la file d'attente de service (SvcQ). Le service (Svc) reçoit un message du SvcQ.

Une fois que vous avez déterminé que le message doit être envoyé à l'arrière du SvcQ, Svc devrait:

  1. Envoyez un accusé de réception à SvcQ.
  2. Envoyez le message à un autre échange, notre psuedo-DLX chronométré
  3. Le psuedo-DLX peut être configuré pour libérer des messages au (BACK OF !!) SvcQ à un certain intervalle de temps