Quando um consumidor falha ao processar uma mensagem ou o processamento atinge o tempo limite, o ApsaraMQ for RocketMQ reenvia a mensagem automaticamente com base em uma política de nova tentativa. Após o esgotamento de todas as tentativas, a mensagem é movida para uma fila de mensagens mortas. Consuma mensagens nessas filas para restaurar suas operações de negócio.
Observações de uso
O ID da mensagem permanece inalterado durante todas as tentativas.
A nova tentativa de consumo funciona apenas no modo de consumo por cluster. No modo de consumo por broadcast, as mensagens com falha não são reenviadas; o consumidor avança para a próxima mensagem.
Como funciona
Uma mensagem passa pelos seguintes estados:
|
Estado |
Descrição |
|
Ready |
A mensagem está na fila do broker e disponível para consumo. |
|
Inflight |
Um consumidor puxou a mensagem e a está processando. Ainda não há resultado retornado. |
|
WaitingRetry |
O consumo falhou ou atingiu o tempo limite. A mensagem aguarda o intervalo de nova tentativa antes de retornar ao estado Ready. |
|
Commit |
O consumidor retornou uma resposta de sucesso. O consumo foi concluído. |
|
DLQ |
Se o recurso de retenção de mensagens mortas estiver ativado, a mensagem será movida para o tópico de mensagens mortas após o esgotamento de todas as tentativas. |

Tempo de nova tentativa
O intervalo entre duas tentativas consecutivas de consumo possui três componentes:
Intervalo entre tentativas = duração do consumo + intervalo de nova tentativa + tempo no estado Ready

Por exemplo, suponha que uma mensagem aguarde 5 segundos no estado Ready e leve 6 segundos para ser processada antes de falhar. Com um intervalo de nova tentativa de 10 segundos:
0 s — A mensagem entra no estado Ready.
5 s — O consumidor puxa a mensagem (Inflight).
11 s — O consumo falha após 6 segundos. A mensagem entra em WaitingRetry.
21 s — Após o intervalo de nova tentativa de 10 segundos, a mensagem retorna ao estado Ready.
26 s — O consumidor puxa a mensagem novamente para a próxima tentativa.
Intervalo total: 6 + 10 + 5 = 21 segundos.
Políticas de nova tentativa para TCP
Mensagens ordenadas
|
Configuração |
Detalhes |
|
Intervalo de nova tentativa |
Definido pelo parâmetro |
|
Máximo de novas tentativas |
Definido pelo parâmetro |
Mensagens não ordenadas
|
Configuração |
Detalhes |
|
Intervalo de nova tentativa |
Segue um cronograma escalonado predefinido (consulte a tabela abaixo). Intervalos personalizados não são suportados para mensagens não ordenadas. |
|
Máximo de novas tentativas |
Definido pelo parâmetro |
Se MaxReconsumeTimes exceder 16, o cronograma predefinido se aplica às primeiras 16 tentativas. Todas as tentativas subsequentes usam um intervalo fixo de 2 horas.
Cronograma de intervalo de nova tentativa para mensagens não ordenadas
|
Tentativa |
Intervalo |
Tentativa |
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 |
Políticas de nova tentativa para HTTP
As políticas de nova tentativa HTTP são predefinidas e não podem ser modificadas.
|
Tipo de mensagem |
Intervalo de nova tentativa |
Máximo de novas tentativas |
|
Ordenada |
1 minuto |
288 |
|
Não ordenada |
5 minutos |
288 |
Configure comportamento de nova tentativa para TCP
Ative nova tentativa
Para acionar uma nova tentativa quando o consumo falhar no modo de consumo por cluster, implemente a interface MessageListener com uma das seguintes abordagens:
**Retornar
Action.ReconsumeLater** (recomendado)Retornar
nullLançar uma exceção
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");
}
}
Desativar nova tentativa
Para evitar o reenvio, capture todas as exceções na lógica de consumo e retorne 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 o intervalo de nova tentativa e o máximo de tentativas
A configuração personalizada de nova tentativa requer o SDK de cliente TCP para Java versão 1.2.2 ou posterior. Para mais informações, consulte Notas de versão.
Defina MaxReconsumeTimes e SuspendTimeMillis nas propriedades do consumidor antes de iniciá-lo. Os intervalos personalizados de nova tentativa aplicam-se apenas a mensagens ordenadas. Mensagens não ordenadas sempre seguem o cronograma 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 os consumidores no mesmo grupo de consumidores compartilham a configuração de nova tentativa. O consumidor iniciado mais recentemente substitui a configuração dos consumidores anteriores. Certifique-se de que todos os consumidores em um grupo usem valores idênticos para MaxReconsumeTimes e SuspendTimeMillis.
Consultar a contagem de novas tentativas
Após receber uma mensagem, chame message.getReconsumeTimes() para verificar quantas vezes ela foi submetida a nova tentativa:
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;
}
}
Melhores práticas
Comece com os valores padrão de nova tentativa. O cronograma padrão para mensagens não ordenadas (escalando de 10 segundos a 2 horas em 16 tentativas) funciona bem para a maioria das falhas transitórias. Faça ajustes somente após observar os padrões reais de falha do seu sistema.
Configure o monitoramento da fila de mensagens mortas. As mensagens que esgotam todas as tentativas são movidas para essa fila. Monitore-a e configure alertas para investigar e reprocessar rapidamente as mensagens com falha.
Mantenha a lógica de consumo idempotente. Como as mensagens podem ser entregues mais de uma vez durante as novas tentativas, projete seu consumidor para lidar com segurança com o processamento duplicado.
Evite consumos de longa duração. Se o processamento demorar muito, a mensagem pode atingir o tempo limite e acionar uma nova tentativa desnecessária. Divida tarefas longas em etapas menores ou aumente o tempo limite de consumo.
Próximos passos
Filas de mensagens mortas — Gerencie mensagens que falham após todas as tentativas.
Notas de versão — Verifique os requisitos de versão do SDK de cliente TCP.