RabbitMQ PRECONDITION_FAILED – etiqueta de entrega desconocida

2 minutos de lectura

Tenemos una aplicación PHP que reenvía mensajes de RabbitMQ a dispositivos conectados a través de una conexión WebSocket (extensión PHP AMQP pecl v1.7.1 y RabbitMQ 3.6.6).

Los mensajes se consumen de una serie de colas (1 por conexión de websocket) y el consumidor los reconoce cuando recibimos la confirmación a través del websocket de que se ha recibido el mensaje (para que podamos volver a poner en cola los mensajes que no se entregan en un plazo aceptable). Esto se hace de manera no bloqueante.

El 99% de las veces, esto funciona perfectamente, pero muy ocasionalmente recibimos un error “RabbitMQ PRECONDITION_FAILED – etiqueta de entrega desconocida”. Esto cierra el canal. A mi entender, esta excepción es el resultado de una de las siguientes condiciones:

  1. El mensaje tiene ya sido aceptado o rechazado.
  2. Se intenta un acuse de recibo a través de un canal en el que no se entregó el mensaje.
  3. Se intenta un acuse de recibo después de que haya expirado el tiempo de espera del mensaje (ttl).

Hemos implementado protecciones para cada uno de los casos anteriores, pero el problema continúa.

Me doy cuenta de que hay varios detalles de implementación que podrían afectar esto, pero a nivel conceptual, ¿hay otros casos de falla que no hayamos considerado y que debamos manejar? o hay una mejor manera de lograr la funcionalidad descrita anteriormente?

“PRECONDITION_FAILED – etiqueta de entrega desconocida” generalmente ocurre debido a la confirmación doble, la confirmación en canales incorrectos o la confirmación de mensajes que no deberían confirmarse.

Entonces, en el mismo caso, estás tratando de ejecutar basic.ack dos veces o basic.ack usando otro canal

  • Como respondió @DenisKolodin, creo que primero deberíamos verificar si el auto_ack se establece en False. Si es cierto, obtenemos el mismo error al reconocer manualmente.

    – Venkatesh Dharavath

    19 de marzo de 2021 a las 9:27


Avatar de usuario de Mercury
Mercurio

(Solución a continuación)

Citando a Jan Grzegorowski de su blog:

Si tiene problemas con el mensaje de error 406 que se incluye en el título de esta publicación, es posible que le interese leer la historia completa.

Problema

Estaba usando amqplib para conectar el procesador de mensajes basado en NodeJS con el agente RabbitMQ. Todo parece estar funcionando bien, pero de vez en cuando aparece el mensaje 406 (FALLO EN LA PRECONDICIÓN) en el registro:

"Error: Channel closed by server: 406 (PRECONDITION-FAILED) with message "PRECONDITION_FAILED - unknown delivery tag 1"

Solución

Manteniendo las cosas simples:

  • Tienes que ACK mensajes en el mismo orden en que llegan a tu sistema
  • No puede ACK mensajes en un canal diferente al que llegan. Si infringe alguna de estas reglas, se enfrentará al mensaje de error 406 (FALLO DE CONDICIÓN PREVIA).

respuesta original

Puede suceder si establece no-ack opción de un Consumidor a true eso significa que no deberías llamar ack función manualmente:

https://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.consume.no-ack

La solución: colocar no-ack bandera a false.

Si reconoce dos veces el mismo mensaje, puede tener este error.

Avatar de usuario de Melardev
melardev

Una variación de lo que dijeron arriba sobre golpearlo dos veces:
hay una situación “oscura” en la que está respondiendo un mensaje más de una vez, que es cuando responde un mensaje con multiple parámetro establecido en verdadero, lo que significa que todos los mensajes anteriores al que está tratando de confirmar también serán confirmados.
Por lo tanto, si intenta confirmar uno de los mensajes que fueron “reconocidos automáticamente” configurando múltiple en verdadero, entonces estaría tratando de “reconocerlo” varias veces y, por lo tanto, el error, confuso, pero espero que lo entienda después de algunas lecturas.

  • Intenté editar para que tu respuesta sea más clara. golpeó el problema “la cola de edición está llena”. intente dividirlo en párrafos con las líneas en los siguientes comentarios

    – Yilmaz Durmaz

    13/01/2022 a las 11:30

  • Una variación de lo que dijeron arriba sobre tocarlo dos veces:

    – Yilmaz Durmaz

    13/01/2022 a las 11:30

  • hay una situación “oscura” en la que está acusando un mensaje más de una vez, que es cuando acusa un mensaje con múltiples parámetros establecidos en verdadero, lo que significa que todos los mensajes anteriores al que está tratando de acusar serán confirmados ‘ed también.

    – Yilmaz Durmaz

    13/01/2022 a las 11:30

  • y entonces, si intenta confirmar uno de los mensajes que fueron “reconocidos automáticamente” configurando múltiple en verdadero, entonces estaría tratando de “reconocerlo” varias veces y, por lo tanto, el error

    – Yilmaz Durmaz

    13 de enero de 2022 a las 11:31

  • bueno mejore un poco Gracias

    – Melardev

    13 de enero de 2022 a las 22:43

Avatar de usuario de Sifeng
Sifeng

Asegúrese de tener las propiedades de la aplicación correctas:

Si usa RabbitTemplate sin ninguna configuración de canal, use “simple”:

spring.rabbitmq.listener.simple.acknowledge-mode=manual

En este caso, si usa “directo” en lugar de “simple”, recibirá el mismo mensaje de error. Otro se ve así:

spring.rabbitmq.listener.direct.acknowledge-mode=manual

  • Intenté editar para que tu respuesta sea más clara. golpeó el problema “la cola de edición está llena”. intente dividirlo en párrafos con las líneas en los siguientes comentarios

    – Yilmaz Durmaz

    13/01/2022 a las 11:30

  • Una variación de lo que dijeron arriba sobre tocarlo dos veces:

    – Yilmaz Durmaz

    13/01/2022 a las 11:30

  • hay una situación “oscura” en la que está acusando un mensaje más de una vez, que es cuando acusa un mensaje con múltiples parámetros establecidos en verdadero, lo que significa que todos los mensajes anteriores al que está tratando de acusar serán confirmados ‘ed también.

    – Yilmaz Durmaz

    13/01/2022 a las 11:30

  • y entonces, si intenta confirmar uno de los mensajes que fueron “reconocidos automáticamente” configurando múltiple en verdadero, entonces estaría tratando de “reconocerlo” varias veces y, por lo tanto, el error

    – Yilmaz Durmaz

    13 de enero de 2022 a las 11:31

  • bueno mejore un poco Gracias

    – Melardev

    13 de enero de 2022 a las 22:43

¿Ha sido útil esta solución?