Cuando un consumidor no logra procesar un mensaje o se agota el tiempo de procesamiento, ApsaraMQ for RocketMQ vuelve a entregar el mensaje automáticamente según una directiva de reintento. Una vez que se agotan todos los intentos de reintento, el mensaje se traslada a una dead-letter queue. Puede consumir mensajes de las colas de mensajes no entregados para restaurar su negocio.
Notas de uso
El ID del mensaje permanece sin cambios durante todos los intentos de reintento.
El reintento de consumo funciona únicamente en el modo de consumo por clúster. En el modo de consumo por difusión, los mensajes con errores no se vuelven a entregar; el consumidor omite el mensaje y pasa al siguiente.
Funcionamiento
Un mensaje transita por los siguientes estados:
|
Estado |
Descripción |
|
Ready |
El mensaje está en la cola del broker y disponible para su consumo. |
|
Inflight |
Un consumidor ha extraído el mensaje y lo está procesando. Aún no se ha devuelto ningún resultado. |
|
WaitingRetry |
El consumo falló o se agotó el tiempo de espera. El mensaje espera a que transcurra el intervalo de reintento antes de volver al estado Ready. |
|
Commit |
El consumidor devolvió una respuesta de éxito. El consumo se completó. |
|
DLQ |
Si la función de retención de mensajes no entregados está habilitada, el mensaje se traslada al tema de mensajes no entregados después de agotar todos los intentos de reintento. |

Temporización de reintentos
El intervalo entre dos intentos consecutivos de consumo tiene tres componentes:
Intervalo entre intentos = duración del consumo + intervalo de reintento + tiempo en estado Ready

Por ejemplo, suponga que un mensaje espera 5 segundos en el estado Ready y tarda 6 segundos en procesarse antes de fallar. Con un intervalo de reintento de 10 segundos:
0 s: El mensaje entra en el estado Ready.
5 s: El consumidor extrae el mensaje (Inflight).
11 s: El consumo falla después de 6 segundos. El mensaje entra en WaitingRetry.
21 s: Tras el intervalo de reintento de 10 segundos, el mensaje vuelve a Ready.
26 s: El consumidor extrae el mensaje nuevamente para el siguiente intento.
Intervalo total: 6 + 10 + 5 = 21 segundos.
Directivas de reintento para TCP
Mensajes ordenados
|
Configuración |
Detalles |
|
Intervalo de reintento |
Se establece con el parámetro |
|
Reintentos máximos |
Se establece con el parámetro |
Mensajes no ordenados
|
Configuración |
Detalles |
|
Intervalo de reintento |
Sigue un programa predefinido escalonado (consulte la tabla a continuación). No se admiten intervalos personalizados para mensajes no ordenados. |
|
Reintentos máximos |
Se establece con el parámetro |
Si MaxReconsumeTimes supera 16, el programa predefinido se aplica a los primeros 16 reintentos. Todos los reintentos posteriores utilizan un intervalo fijo de 2 horas.
Programa de intervalos de reintento para mensajes no ordenados
|
Reintento |
Intervalo |
Reintento |
Intervalo |
|
1 |
10 segundos |
9 |
7 minutos |
|
2 |
30 segundos |
10 |
8 minutos |
|
3 |
1 minuto |
11 |
9 minutos |
|
4 |
2 minutos |
12 |
10 minutos |
|
5 |
3 minutos |
13 |
20 minutos |
|
6 |
4 minutos |
14 |
30 minutos |
|
7 |
5 minutos |
15 |
1 hora |
|
8 |
6 minutos |
16 |
2 horas |
Directivas de reintento para HTTP
Las directivas de reintento HTTP están predefinidas y no se pueden modificar.
|
Tipo de mensaje |
Intervalo de reintento |
Reintentos máximos |
|
Ordenado |
1 minuto |
288 |
|
No ordenado |
5 minutos |
288 |
Configurar el comportamiento de reintento para TCP
Habilitar el reintento
Para activar un reintento cuando falla el consumo en el modo de consumo por clúster, implemente la interfaz MessageListener con uno de estos enfoques:
**Devolver
Action.ReconsumeLater** (recomendado)Devolver
nullLanzar una excepción
public class MessageListenerImpl implements MessageListener {
@Override
public Action consume(Message message, ConsumeContext context) {
// If the consumption logic throws an exception, the message is retried.
doConsumeMessage(message);
// Method 1: Return Action.ReconsumeLater and retry the message.
return Action.ReconsumeLater;
// Method 2: Return null and retry the message.
return null;
// Method 3: Throw an exception and retry the message.
throw new RuntimeException("Consumer Message exception");
}
}
Deshabilitar el reintento
Para evitar la reentrega, capture todas las excepciones en su lógica de consumo y devuelva Action.CommitMessage:
public class MessageListenerImpl implements MessageListener {
@Override
public Action consume(Message message, ConsumeContext context) {
try {
doConsumeMessage(message);
} catch (Throwable e) {
// Catch all exceptions and return CommitMessage to skip retry.
return Action.CommitMessage;
}
// Consumption succeeded.
return Action.CommitMessage;
}
}
Personalizar el intervalo de reintento y los reintentos máximos
La configuración personalizada de reintentos requiere el SDK de cliente TCP para Java versión 1.2.2 o posterior. Para obtener más información, consulte Release notes.
Establezca MaxReconsumeTimes y SuspendTimeMillis en las propiedades del consumidor antes de iniciar el consumidor. Los intervalos de reintento personalizados se aplican únicamente a mensajes ordenados. Los mensajes no ordenados siempre siguen el programa predefinido.
Properties properties = new Properties();
// Set the maximum number of retries to 20.
properties.put(PropertyKeyConst.MaxReconsumeTimes, "20");
// Set the retry interval to 3,000 milliseconds (ordered messages only).
properties.put(PropertyKeyConst.SuspendTimeMillis, "3000");
Consumer consumer = ONSFactory.createConsumer(properties);
Todos los consumidores del mismo grupo de consumidores comparten la configuración de reintento. El consumidor iniciado más recientemente sobrescribe la configuración de los consumidores anteriores. Asegúrese de que todos los consumidores de un grupo utilicen valores idénticos para MaxReconsumeTimes y SuspendTimeMillis.
Consultar el recuento de reintentos
Después de que un consumidor reciba un mensaje, llame a message.getReconsumeTimes() para comprobar cuántas veces se ha reintentado el mensaje:
public class MessageListenerImpl implements MessageListener {
@Override
public Action consume(Message message, ConsumeContext context) {
// Get the current retry count.
System.out.println(message.getReconsumeTimes());
return Action.CommitMessage;
}
}
Mejores prácticas
Comience con los valores de reintento predeterminados. El programa predeterminado para mensajes no ordenados (que escala de 10 segundos a 2 horas en 16 reintentos) funciona bien para la mayoría de los fallos transitorios. Ajústelo solo después de observar los patrones reales de fallos de su sistema.
Configure el monitoreo de la cola de mensajes no entregados. Los mensajes que agotan todos los reintentos se trasladan a una cola de mensajes no entregados. Monitoree esta cola y configure alertas para poder investigar y reprocesar rápidamente los mensajes con errores.
Mantenga la lógica de consumo idempotente. Dado que los mensajes pueden entregarse más de una vez durante los reintentos, diseñe su consumidor para manejar el procesamiento duplicado de forma segura.
Evite consumos de larga duración. Si el procesamiento tarda demasiado, el mensaje puede agotar el tiempo de espera y activar un reintento innecesario. Divida las tareas largas en pasos más pequeños o aumente el tiempo de espera de consumo.
Pasos siguientes
Dead-letter queues: Gestione los mensajes que fallan después de agotar todos los intentos de reintento.
Release notes: Compruebe los requisitos de versión del SDK de cliente TCP.