Quando um producer envia uma mensagem ao broker do ApsaraMQ for RocketMQ, a solicitação pode falhar devido a problemas de rede, reinicializações do broker ou limites de capacidade. O SDK cliente gerencia essas falhas por meio de dois mecanismos integrados:
Nova tentativa de envio: reenvia automaticamente as mensagens com falha até que tenham sucesso ou atinjam o limite de tentativas.
Limitação (throttling): protege o broker contra sobrecarga ao rejeitar solicitações quando a capacidade é insuficiente.
Esses mecanismos atuam em conjunto: quando a limitação aciona uma rejeição, o mecanismo de nova tentativa utiliza backoff exponencial para reenviar a mensagem sem sobrecarregar ainda mais o broker.
Nova tentativa de envio
Processo de nova tentativa
O SDK cliente possui lógica de nova tentativa integrada. Se uma solicitação de envio falhar, o SDK reenvia a mensagem automaticamente, eliminando a necessidade de código de repetição no nível da aplicação.
Defina o número máximo de tentativas ao inicializar o producer. Caso uma solicitação falhe, o SDK continuará tentando até entregar a mensagem ou atingir o limite de tentativas. Após a falha na última tentativa, o SDK retorna um erro à sua aplicação.
O comportamento de nova tentativa varia conforme o modo de envio:
|
Modo de envio |
Comportamento da thread |
Na falha final |
|
Síncrono |
A thread chamadora fica bloqueada durante toda a sequência de tentativas |
O SDK lança uma exceção |
|
Assíncrono |
A thread chamadora não é bloqueada |
O SDK entrega um evento de callback de falha |
Gatilhos de nova tentativa
Duas categorias de falha acionam novas tentativas:
Falhas no lado do cliente
Uma exceção de rede causa falha na conexão ou timeout na solicitação.
O broker está sendo reiniciado ou desimplantado, resultando em falhas de conexão.
O broker apresenta lentidão, causando timeouts nas solicitações.
Erros no lado do broker
Erro de lógica do sistema: falha interna de processamento no broker.
Erro de limitação do sistema: o broker rejeita a solicitação porque excedeu a capacidade. Consulte Limitação.
Mensagens transacionais suportam apenas tentativas transparentes. O SDK não tenta reenviar mensagens transacionais em caso de exceções de rede ou timeouts.
Intervalo de nova tentativa
O intervalo entre tentativas depende do tipo de erro:
|
Tipo de erro |
Intervalo de nova tentativa |
|
Todos os erros, exceto limitação |
Imediato (sem atraso) |
|
Erro de limitação do sistema |
Backoff exponencial com jitter |
Para erros de limitação, o SDK aplica backoff exponencial com os seguintes parâmetros:
|
Parâmetro |
Descrição |
Padrão |
|
|
Atraso antes da primeira tentativa |
1 segundo |
|
|
Fator de aumento do atraso após cada tentativa |
1,6 |
|
|
Fator de aleatoriedade aplicado a cada atraso |
0,2 |
|
|
Atraso máximo entre tentativas |
120 segundos |
|
|
Timeout mínimo de conexão |
20 segundos |
O algoritmo de backoff funciona da seguinte maneira:
ConnectWithBackoff()
current_backoff = INITIAL_BACKOFF
current_deadline = now() + INITIAL_BACKOFF
while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT)) != SUCCESS)
SleepUntil(current_deadline)
current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF)
current_deadline = now() + current_backoff +
UniformRandom(-JITTER * current_backoff, JITTER * current_backoff)
Para a especificação completa, consulte backoff de conexão gRPC.
Entenda o orçamento total de tempo de nova tentativa
O SDK expõe apenas um controle de repetição: o número máximo de tentativas. No modo síncrono, a thread chamadora fica bloqueada durante toda a sequência de tentativas; portanto, o tempo total de bloqueio depende da relação entre o timeout por solicitação e o número máximo de tentativas:
Total blocking time (worst case) = max_retries x per_request_timeout + sum_of_backoff_delays
Para erros sem limitação (nova tentativa imediata), o atraso de backoff é zero:
Total blocking time = max_retries x per_request_timeout
Em erros de limitação, os atrasos de backoff acumulam-se exponencialmente. Por exemplo, com os parâmetros padrão e 5 tentativas:
|
Tentativa |
Atraso de backoff (aproximado) |
Atraso acumulado |
|
1 |
1 s |
1 s |
|
2 |
1,6 s |
2,6 s |
|
3 |
2,56 s |
5,16 s |
|
4 |
4,1 s |
9,26 s |
|
5 |
6,55 s |
15,81 s |
Avalie conjuntamente o timeout por solicitação e o número máximo de tentativas para evitar bloqueios excessivos da thread chamadora no modo síncrono.
Gerencie mensagens com falha após esgotamento das tentativas
As tentativas integradas não garantem a entrega. Se todas falharem, o SDK retornará um erro. Capture esse erro em sua aplicação e implemente uma estratégia de fallback:
Grave a mensagem com falha em um log local ou armazenamento de dead-letter para reprocessamento posterior.
Acione alertas no sistema de monitoramento para investigar a causa raiz.
Trate mensagens duplicadas decorrentes de novas tentativas
Quando ocorre timeout em uma solicitação de envio, o SDK não consegue determinar se o broker já recebeu e armazenou a mensagem. Uma nova tentativa pode gerar duplicidade no broker, o que representa uma troca fundamental em sistemas de entrega "pelo menos uma vez" (at-least-once).
Para lidar com duplicatas, projete seus consumers para processamento idempotente:
Atribua a cada mensagem uma chave de negócio exclusiva (como ID de pedido ou ID de transação).
Verifique se a chave já foi processada antes de iniciar o tratamento.
Utilize restrições de banco de dados ou caches de deduplicação para garantir unicidade.
Limitação (Throttling)
A limitação é um mecanismo operacional normal em sistemas de mensageria em nuvem. Quando a capacidade do sistema é insuficiente ou o uso ultrapassa um limiar predefinido, o broker do ApsaraMQ for RocketMQ rejeita imediatamente a solicitação e retorna um erro de limitação do sistema. A lógica de nova tentativa integrada do SDK gerencia essa solicitação rejeitada usando backoff exponencial.
Gatilhos de limitação
Os cenários abaixo acionam a limitação:
Pico de pressão de armazenamento: um consumer group começa a consumir a partir do offset máximo de uma fila. Em situações como implantações de negócios, em que o consumo deve iniciar em um horário específico, a pressão de armazenamento na fila aumenta drasticamente. Para mais informações, consulte Gerenciamento de progresso do consumidor.
Acúmulo de mensagens: quando os consumers não acompanham a taxa de mensagens recebidas, as mensagens não consumidas se acumulam na fila. Se o acúmulo ultrapassar o limiar, o broker ativa a limitação para reduzir a pressão sobre o sistema downstream.
Códigos de erro e comportamento de nova tentativa por tipo de cliente
Ao ocorrer limitação, o código de erro e o comportamento de nova tentativa dependem do protocolo do seu cliente.
Clientes gRPC
|
Item |
Valor |
|
Código de erro |
|
|
Palavra-chave da mensagem de erro |
|
|
Comportamento de nova tentativa |
Tentativa automática com backoff exponencial |
Clientes Remoting
|
Item |
Valor |
|
Código de erro |
|
|
Palavra-chave da mensagem de erro |
|
O comportamento de nova tentativa para clientes Remoting varia conforme a versão do SDK:
|
SDK |
Comportamento de nova tentativa sob limitação |
|
SDK de cliente TCP do ApsaraMQ for RocketMQ para Java < 1.9.0.Final |
Sem nova tentativa |
|
SDK de cliente TCP do ApsaraMQ for RocketMQ para Java >= 1.9.0.Final |
Tentativa automática com backoff exponencial |
|
SDK open-source Apache RocketMQ (producer) |
Sem nova tentativa |
|
SDK open-source Apache RocketMQ (consumer) |
Tentativa automática com backoff exponencial |
Caso sua versão do SDK não tente novamente automaticamente em erros de limitação, implemente uma lógica de repetição com backoff exponencial no código da sua aplicação.
Para versões de cliente suportadas, consulte Compatibilidade de SDK.
Previna e gerencie a limitação
Monitore a capacidade antes de picos de tráfego
Utilize os recursos de observabilidade do ApsaraMQ for RocketMQ para acompanhar o uso e a capacidade do sistema. Antes de implantações de negócios ou picos de tráfego previstos:
Verifique se sua instância possui recursos suficientes para o tráfego esperado.
Analise o atraso dos consumer groups para identificar riscos de acúmulo.
Dimensione sua instância ou otimize o throughput dos consumers, se necessário.
Gerencie limitações inesperadas em tempo de execução
Se ocorrer limitação inesperada e as tentativas integradas do SDK não conseguirem recuperar:
Redirecione as solicitações para um sistema de fallback até que a condição de limitação seja resolvida.
Registre eventos de limitação em log (procure pelo código de erro
530/TOO_MANY_REQUESTSpara gRPC ou215/messages flow controlpara Remoting) para auxiliar no diagnóstico da causa raiz.