28 de abril de 20263 min de leitura

Superando o gargalo do processamento "all-or-nothing" no Azure Service Bus

Swapnil Nagar

Azure

Banner - Superando o gargalo do processamento "all-or-nothing" no Azure Service Bus

No ecossistema de arquiteturas orientadas a eventos no Azure, o Azure Service Bus é uma peça fundamental para garantir a comunicação desacoplada e resiliente. Entretanto, um padrão de implementação muito comum — o processamento de batches sem granularidade — costuma gerar desafios técnicos que impactam diretamente a performance e a saúde financeira das operações em cloud.

O problema: A falha "all-or-nothing"

Ao utilizar o Azure Functions com o gatilho (trigger) de Service Bus em modo batch, a função recebe um conjunto de mensagens para otimizar o throughput. O grande gargalo ocorre quando um subconjunto dessas mensagens falha. No modelo padrão, a falha em um único item resulta no rollback de todo o batch. Todos os eventos são retornados à fila para reprocessamento, incluindo aqueles que foram concluídos com sucesso.

Fluxo de processamento de batch

Isso desencadeia uma série de efeitos colaterais conhecidos por engenheiros que operam sistemas distribuídos:

  • Processamento duplicado: Mensagens reinjetadas desnecessariamente sobrecarregam os sistemas de jusante (downstream).
  • Desperdício de compute: Custos adicionais de execução de função e consumo de I/O em tarefas que já deveriam estar encerradas.
  • Ciclos de retry infinitos: Uma mensagem "poison" pode bloquear o fluxo, forçando o reprocessamento contínuo de itens saudáveis.
  • Aumento da complexidade de idempotência: As aplicações consumidoras precisam implementar lógica adicional complexa para lidar com a natureza não determinística dessas reentregas.

A solução: Per-message settlement

Para mitigar esses riscos operacionais, o Azure Functions oferece a capacidade de liquidação por mensagem. Em vez de tratar o batch como um bloco monolítico, é possível realizar a resolução (settlement) de cada evento individualmente. Dependendo do resultado do processamento, você pode definir a ação específica para cada item:

  • Complete: Finaliza a mensagem (sucesso).
  • Abandon: Devolve a mensagem à fila para um novo processamento, ideal para erros transitórios.
  • Dead-letter: Direciona mensagens malformadas para a fila de mensagens mortas, isolando o erro.
  • Defer: Retém a mensagem para processamento agendado, útil quando há dependência de ordem.

Impacto estratégico para empresas brasileiras

A adoção de per-message settlement transcende a escrita de código; é uma decisão de eficiência operacional e FinOps. Ao evitar o reprocessamento redundante, reduzimos drasticamente o consumo de instâncias de computação e chamadas de API, impactando positivamente a fatura mensal do Azure.

Além disso, do ponto de vista de SecOps e resiliência, a detecção isolada de mensagens poison evita que falhas em fluxos de menor prioridade ou corrompidos afetem a entrega de pacotes de dados críticos para o negócio, mantendo o SLA e a estabilidade da plataforma em ambientes de escala massiva.

Implementação prática

Para habilitar este controle, é necessário desativar o autoCompleteMessages e configurar o cardinality como many. Segue exemplo em .NET (C# Isolated Worker):

public async Task ProcessOrderBatch(
    [ServiceBusTrigger("orders-queue", Connection = "ServiceBusConnection")]
    ServiceBusReceivedMessage[] messages,
    ServiceBusMessageActions messageActions)
{
    foreach (var message in messages)
    {
        try
        {
            var order = message.Body.ToObjectFromJson<Order>();
            await ProcessOrder(order);
            await messageActions.CompleteMessageAsync(message);       
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed {MessageId}", message.MessageId);
            await messageActions.DeadLetterMessageAsync(message);     
        }
    }
}

Ao utilizar a injeção do ServiceBusMessageActions, o time de engenharia ganha o controle necessário para implementar políticas de exponential backoff sem a necessidade de infraestrutura adicional (como filas de retry externas), simplificando a arquitetura global e reduzindo a superfície de erro.


Artigo originalmente publicado em Azure Updates - Latest from Azure Charts.

Gostou? Compartilhe:
Precisa de ajuda?Fale com nossos especialistas 👋
Avatar Walcew - Headset