Compartilhar via


Práticas recomendadas para melhorias de desempenho usando o Sistema de Mensagens do Barramento de Serviço

Este artigo descreve como usar o Barramento de Serviço do Azure para otimizar o desempenho na troca de mensagens agenciadas. A primeira parte deste artigo descreve diferentes mecanismos para ajudar a melhorar o desempenho. A segunda parte oferece orientação sobre o uso do Barramento de Serviço de uma maneira que possa oferecer o melhor desempenho em um determinado cenário.

Ao longo deste artigo, o termo "cliente" refere-se a qualquer entidade que acesse o Barramento de Serviço. Um cliente pode assumir a função de um remetente ou de um receptor. O termo "remetente" é usado para um cliente de fila ou cliente de tópico do Barramento de Serviço que envia mensagens para uma fila ou um tópico do Barramento de Serviço. O termo "receptor" refere-se a um cliente de fila ou cliente de assinatura do Barramento de Serviço que recebe mensagens de uma fila ou uma assinatura do Barramento de Serviço.

Planejamento de recursos e considerações

Assim como com qualquer recurso técnico, o planejamento responsável é fundamental para garantir que o Barramento de Serviço do Azure forneça o desempenho esperado pelo aplicativo. A configuração ou a topologia corretas para seus namespaces do Barramento de Serviço dependem de uma série de fatores que envolvem a arquitetura do aplicativo e como cada um dos recursos do Barramento de Serviço é usado.

Tipo de preço

O Barramento de Serviço oferece vários tipos de preço. É recomendável escolher a camada apropriada aos requisitos do seu aplicativo.

  • Camada Standard – adequada para ambientes de desenvolvedor/teste ou cenários de baixa taxa de transferência nos quais os aplicativos não sejam sensíveis à limitação.

  • Camada Premium – adequada para ambientes de produção com requisitos de produtividade variados em que a latência e a taxa de transferência necessitam ser previsíveis. Além disso, os namespaces premium do Barramento de Serviço e podem ser dimensionados automaticamente para acomodar picos na taxa de transferência.

Observação

Se a camada correta não for escolhida, haverá o risco de sobrecarregar o namespace do Barramento de Serviço, o que pode levar à limitação.

A limitação não leva à perda de dados. Os aplicativos que aproveitam o SDK do Barramento de Serviço podem utilizar a política de repetição padrão para garantir que os dados sejam, por fim, aceitos pelo Barramento de Serviço.

Calculando a taxa de transferência para o Premium

Os dados enviados ao Barramento de Serviço são serializados para binários e, em seguida, desserializados quando recebidos pelo receptor. Assim, embora os aplicativos pensem em mensagens como unidades atômicas de trabalho, o Barramento de Serviço mede a taxa de transferência em termos de bytes (ou megabytes).

Ao calcular o requisito de taxa de transferência, considere os dados que estão sendo enviados para o Barramento de Serviço (entrada) e os dados recebidos do Barramento de Serviço (saída).

Conforme esperado, a taxa de transferência é maior para conteúdos de mensagens menores que podem ser em enviadas juntas em lote.

Parâmetros de comparação

Aqui está um exemplo do GitHub que você pode executar para ver a taxa de transferência esperada recebida para o namespace do Barramento de Serviço. Em nossos testes de parâmetro de comparação, observamos aproximadamente 4 MB/segundo por MU (Unidade do Sistema de Mensagens) de entrada e saída.

O exemplo de parâmetro de comparação não usa recursos avançados, portanto, a taxa de transferência que seus aplicativos observam é diferente, com base em seus cenários.

Considerações de computação

O Barramento de Serviço opera vários processos em segundo plano que podem afetar a utilização da computação. Isso inclui, mas não se limita a, temporizadores, agendamentos e emissão de métricas. Além disso, o uso de determinados recursos do Barramento de Serviço exige utilização de computação que pode diminuir a taxa de transferência esperada. Alguns desses recursos são -

  1. Sessões.
  2. Realizar fan-out para várias assinaturas em um único tópico.
  3. Executar muitos filtros em uma única assinatura.
  4. Mensagens agendadas.
  5. Mensagens adiadas.
  6. Transações.
  7. Janela de tempo de eliminação e duplicação.
  8. Encaminhar para (encaminhamento de uma entidade para outra).

Se o aplicativo usar qualquer um dos recursos acima e você não estiver recebendo a taxa de transferência esperada, você poderá examinar as métricas de uso da CPU e considerar escalar verticalmente o namespace Premium do Barramento de Serviço. Você também pode utilizar o Azure Monitor para dimensionar automaticamente o namespace do Barramento de Serviço. É recomendável aumentar o número de MUs (Unidades de Mensagem) quando o uso da CPU exceder 70% para garantir o desempenho ideal.

Fragmentação entre namespaces

Embora escalar verticalmente a Computação (Unidades do Sistema de Mensagens) alocada para o namespace seja uma solução mais fácil, ela pode não fornecer um aumento linear na taxa de transferência. Isso ocorre devido aos internos do Barramento de Serviço (armazenamento, rede etc.), que podem estar limitando a taxa de transferência.

Nesse caso, a solução mais limpa é fragmentar suas entidades (filas e tópicos) em diferentes namespaces Premium do Barramento de Serviço. Você também pode considerar a fragmentação entre namespaces diferentes em diferentes regiões do Azure.

Protocolos

O Barramento de Serviço permite que os clientes enviem e recebam mensagens por meio de um destes três protocolos:

  1. Advanced Message Queuing Protocol (AMQP)
  2. Protocolo do sistema de mensagens do Barramento de Serviço (SBMP)
  3. Protocolo HTTP

O AMQP é o mais eficiente, pois mantém a conexão com o Barramento de Serviço. Também implementa o envio em lote e a pré-busca. A menos que mencionado explicitamente, todo o conteúdo deste artigo supõe o uso do AMQP ou do SBMP.

Importante

O protocolo SBMP só está disponível para .NET Framework. AMQP é o padrão para .NET Standard.

Em 30 de setembro de 2026, desativaremos o suporte do protocolo SBMP para o Barramento de Serviço do Azure, para que você não possa mais usar esse protocolo após 30 de setembro de 2026. Migre para as bibliotecas mais recentes do SDK do Barramento de Serviço do Azure usando o protocolo AMQP, que oferece atualizações de segurança críticas e funcionalidades aprimoradas, antes dessa data.

Para obter mais informações, confira o anúncio de desativação do suporte.

Escolher o SDK do .NET do Barramento de Serviço apropriado

O Azure.Messaging.ServiceBus pacote é o mais recente SDK do .NET do Barramento de Serviço do Microsoft Azure disponível a partir de novembro de 2020. Há dois SDKs do .NET mais antigos que continuarão a receber correções críticas de bug até 30 de setembro de 2026, mas incentivamos você a usar o SDK mais recente. Leia o Guia de migração para obter detalhes sobre como se mover dos SDKs mais antigos.

Pacote NuGet Namespaces primários Plataformas mínimas Protocolos
Azure.Messaging.ServiceBus (mais recente) Azure.Messaging.ServiceBus
Azure.Messaging.ServiceBus.Administration
.NET Core 2.0
.NET Framework 4.6.1
Mono 5.4
Plataforma Universal do Windows 10.0.16299
AMQP
HTTP
Microsoft.Azure.ServiceBus Microsoft.Azure.ServiceBus
Microsoft.Azure.ServiceBus.Management
.NET Core 2.0
.NET Framework 4.6.1
Mono 5.4
Plataforma Universal do Windows 10.0.16299
AMQP
HTTP

Para obter mais informações sobre o suporte mínimo à plataforma .NET Standard, consulte Suporte à implementação do .NET.

Em 30 de setembro de 2026, desativaremos as bibliotecas do SDK do Barramento de Serviço do Azure WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus e com.microsoft.azure.servicebus, que não estão em conformidade com as diretrizes do SDK do Azure. Também encerraremos o suporte ao protocolo SBMP, portanto, ele não poderá mais ser usado após 30 de setembro de 2026. Antes dessa data, migre para as bibliotecas mais recentes do SDK do Azure, que oferecem atualizações de segurança críticas e funcionalidades aprimoradas.

Embora as bibliotecas mais antigas ainda poderão ser usadas após 30 de setembro de 2026, elas não receberão mais suporte e atualizações oficiais da Microsoft. Para obter mais informações, confira o anúncio de desativação do suporte.

Reutilizando fábricas e clientes

Os objetos do Barramento de Serviço que interagem com o serviço, como ServiceBusClient, ServiceBusSender, ServiceBusReceiver e ServiceBusProcessor, devem ser registrados para injeção de dependência como singletons (ou instanciados uma vez e compartilhados). O ServiceBusClient (factory) pode ser registrado para injeção de dependência com o ServiceBusClientBuilderExtensions.

Recomendamos que você não feche ou descarte esses objetos depois de enviar ou receber cada mensagem. Fechar ou descartar os objetos específicos da entidade (ServiceBusSender/Receiver/Processor) resulta na exclusão do link para o serviço do Barramento de Serviço. Descartar o ServiceBusClient resulta na exclusão da conexão com o serviço do Barramento de Serviço.

Essas diretrizes não se aplicam ao ServiceBusSessionReceiver, pois seu tempo de vida é o mesmo que a sessão em si. Para aplicativos que trabalham com o ServiceBusSessionReceiver, é recomendável usar uma instância singleton da sessão ServiceBusClient para aceitar cada sessão, o que gera um novo ServiceBusSessionReceiver associado a essa sessão. Depois que o aplicativo concluir o processamento dessa sessão, ele deverá descartar o ServiceBusSessionReceiver associado.

A observação a seguir se aplica a todos os SDKs:

Observação

O estabelecimento de uma conexão é uma operação cara que você pode evitar usando o mesmo alocador ou objetos de cliente para diversas operações. Você pode usar esses objetos de cliente com segurança em operações assíncronas simultâneas e de vários threads.

Operações simultâneas

Operações como enviar, receber, excluir e assim por diante, levam algum tempo. Esse tempo inclui o tempo que o serviço do Barramento de Serviço leva para processar a operação e a latência da solicitação e da resposta. Para aumentar o número de operações por hora, elas devem ser executadas simultaneamente.

O cliente agenda operações simultâneas realizando operações assíncronas. A próxima solicitação é iniciada antes que a solicitação anterior seja concluída. O snippet de código a seguir é um exemplo de uma operação de envio assíncrono:

var messageOne = new ServiceBusMessage(body);
var messageTwo = new ServiceBusMessage(body);

var sendFirstMessageTask =
    sender.SendMessageAsync(messageOne).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #1");
    });
var sendSecondMessageTask =
    sender.SendMessageAsync(messageTwo).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #2");
    });

await Task.WhenAll(sendFirstMessageTask, sendSecondMessageTask);
Console.WriteLine("All messages sent");

O código a seguir é um exemplo de uma operação de recebimento assíncrono.

var client = new ServiceBusClient(connectionString);
var options = new ServiceBusProcessorOptions 
{

      AutoCompleteMessages = false,
      MaxConcurrentCalls = 20
};
await using ServiceBusProcessor processor = client.CreateProcessor(queueName,options);
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;

static Task ErrorHandler(ProcessErrorEventArgs args)
{
    Console.WriteLine(args.Exception);
    return Task.CompletedTask;
};

static async Task MessageHandler(ProcessMessageEventArgs args)
{
    Console.WriteLine("Handle message");
    await args.CompleteMessageAsync(args.Message);
}

await processor.StartProcessingAsync();

Modo de recebimento

Ao criar um cliente de fila ou de assinatura, você poderá especificar um modo de recebimento: Bloqueio de pico ou Receber e Excluir. Modo de recebimento padrão é PeekLock. Ao operar no modo padrão, o cliente envia uma solicitação para receber uma mensagem do Barramento de Serviço. Depois que o cliente tiver recebido a mensagem, ele enviará uma solicitação para concluir a mensagem.

Ao definir o modo de recebimento para ReceiveAndDelete, as duas etapas são combinadas em uma única solicitação. Essas etapas reduzem o número total de operações e podem melhorar a taxa de transferência geral da mensagem. Este ganho de desempenho vem com o risco de perda de mensagens.

O Barramento de Serviço não dá suporte a transações para operações de receber e excluir. Além disso, a semântica do bloqueio de pico é necessária para todos os cenários em que o cliente deseje adiar uma mensagem ou enviá-la para as mensagens mortas.

Pré-busca

A pré-busca permite que o cliente de fila ou assinatura carregue mensagens extras do serviço quando ele recebe mensagens. O cliente armazena essas mensagens em um cache local. O tamanho do cache é determinado pelas propriedades ServiceBusReceiver.PrefetchCount. Cada cliente que permite a pré-busca mantém seu próprio cache. Um cache não é compartilhado entre os clientes. Se o cliente iniciar uma operação de recebimento e se o cache estiver vazio, o serviço transmitirá um lote de mensagens. Se o cliente iniciar uma operação de recebimento e se o cache contiver uma mensagem, a mensagem será retirada do cache.

Quando uma mensagem for pré-buscada, ela será bloqueada pelo serviço. Com o bloqueio, a mensagem pré-buscada não pode ser recebida por um receptor diferente. Se o receptor não puder concluir a mensagem antes da expiração do bloqueio, a mensagem ficará disponível para outros destinatários. A cópia pré-buscada da mensagem permanecerá no cache. O receptor que consome a cópia armazenada em cache expirada recebe uma exceção quando tenta concluir essa mensagem. Por padrão, o bloqueio da mensagem expira após 60 segundos. Esse valor pode ser estendido para 5 minutos. Para impedir o consumo de mensagens expiradas, defina o tamanho do cache menor do que o número de mensagens que um cliente pode consumir no intervalo de tempo limite de bloqueio.

Ao usar a expiração de bloqueio padrão de 60 segundos, um bom valor para PrefetchCount é 20 vezes as taxas de processamento máximo de todos os receptores do alocador. Por exemplo, um alocador cria três receptores e cada receptor pode processar até dez mensagens por segundo. A contagem de pré-busca não deve exceder 20 X 3 X 10 = 600. Por padrão, PrefetchCount é definido como 0, o que significa que nenhuma mensagem extra é buscada do serviço.

A pré-busca de mensagens aumenta a taxa de transferência geral de uma fila ou uma assinatura porque reduz o número geral de operações de mensagem, ou as viagens de ida e volta. A busca da primeira mensagem, no entanto, leva mais tempo (devido ao aumento do tamanho da mensagem). O recebimento de mensagens pré-buscadas do cache é mais rápido porque essas mensagens já foram baixadas pelo cliente.

A propriedade de vida útil (TTL) de uma mensagem é verificada pelo servidor no momento em que o servidor envia a mensagem para o cliente. O cliente não verifica a propriedade TTL da mensagem quando a mensagem é recebida. Em vez disso, a mensagem poderá ser recebida mesmo se a TTL da mensagem tiver passado enquanto a mensagem estava armazenada em cache pelo cliente.

A pré-busca não afeta o número de operações faturáveis do sistema de mensagens e está disponível somente para o protocolo de cliente do Barramento de Serviço. O protocolo HTTP não dá suporte à pré-busca. A pré-busca está disponível para as operações de recebimento síncrono e assíncrono.

Para obter mais informações, consulte as propriedades PrefetchCount a seguir:

Você pode definir valores para essas propriedades em ServiceBusReceiverOptions ou ServiceBusProcessorOptions.

Pré-busca e ReceiveMessagesAsync

Embora os conceitos de pré-busca de várias mensagens tenham uma semântica semelhante ao processamento de mensagens em um lote (ReceiveMessagesAsync), há algumas pequenas diferenças que devem ser mantidas em mente ao usar essas abordagens juntas.

A pré-busca é uma configuração (ou modo) no ServiceBusReceiver e ReceiveMessagesAsync é uma operação (que tem semântica solicitação-resposta).

Ao usar essas abordagens juntas, considere os seguintes casos -

  • A pré-busca deve ser maior ou igual ao número de mensagens que você está esperando receber de ReceiveMessagesAsync.
  • A pré-busca pode ser até n/3 vezes o número de mensagens processadas por segundo, em que n é a duração de bloqueio padrão.

Há alguns desafios com uma abordagem aproximada, ou seja, manter a contagem de pré-busca alta, pois isso implica que a mensagem está bloqueada para um receptor específico. Recomendamos que você experimente valores de pré-busca que estão entre os limites mencionados anteriormente e identifique o que se ajusta.

Vários tópicos ou filas

Se uma fila ou tópico não puder processar o número esperado de mensagens, use várias entidades de mensagem. Ao usar várias entidades, crie um cliente dedicado para cada entidade em vez de usar o mesmo cliente para todas as entidades.

Ter mais filas ou tópicos significa que você tem mais entidades para gerenciar no momento da implantação. De uma perspectiva de escalabilidade, realmente não há muita diferença a se notar, pois o Barramento de Serviço já espalha a carga por vários logs internamente; portanto, usar seis filas ou tópicos ou duas filas ou tópicos não fará diferença material.

A camada de serviço que você usa afeta a previsibilidade de desempenho. Se você escolher camada Standard, a taxa de transferência e a latência serão os melhores esforços sobre a infraestrutura multilocatário compartilhada. Outros locatários no mesmo cluster podem afetar sua taxa de transferência. Se você escolher Premium, obterá recursos que oferecem desempenho previsível, e suas várias filas ou tópicos serão processados fora desse pool de recursos. Para obter mais informações, consulte Tipos de preço.

Namespaces particionados

Quando você usa namespaces de camada premium particionados, várias partições com unidades do sistema de mensagens (MU) mais baixas oferecem um melhor desempenho em comparação a uma única partição com MUs mais altas.

Cenários

As seções a seguir descrevem cenários típicos de mensagens e as configurações preferenciais do Barramento de Serviço. As taxas de transferência são classificadas como pequena (menos de 1 mensagem/segundo), moderada (1 mensagem/segundo ou mais, mas menos de 100 mensagens por segundo) e alta (100 mensagens/segundo ou mais). O número de clientes é classificado como pequeno (5 ou menos), moderado (de 5 a 20) e grande (mais de 20).

Fila de alta taxa de transferência

Meta: maximizar a taxa de transferência de uma única fila. O número de remetentes e de receptores é pequeno.

  • Para aumentar a taxa geral de envio para a fila, use diversas fábricas de mensagens para criar remetentes. Para cada remetente, use operações assíncronas ou vários threads.
  • Para aumentar a taxa geral de recebimento da fila, use diversas fábricas de mensagens para criar receptores.
  • Defina a contagem de pré-busca como 20 vezes as taxas máximas de processamento de todos os receptores de uma fábrica. Essa contagem reduz o número de transmissões de protocolo de cliente do Barramento de Serviço.

Várias filas de alta taxa de transferência

Meta: maximize a taxa de transferência geral de diversas filas. A taxa de transferência de uma fila individual é moderada ou alta.

Para obter a taxa de transferência máxima em várias filas, use as configurações descritas para maximizar a taxa de transferência de uma única fila. Além disso, use fábricas diferentes para criar clientes que enviem ou recebam de filas diferentes.

Fila de baixa latência

Meta: minimize a latência de uma fila ou um tópico. O número de remetentes e de receptores é pequeno. A taxa de transferência da fila é pequena ou moderada.

  • Se estiver usando um único cliente, defina a contagem de pré-busca como 20 vezes a taxa de processamento do receptor. Se várias mensagens chegarem à fila ao mesmo tempo, o protocolo de cliente do Barramento de Serviço transmite todas ao mesmo tempo. Quando o cliente receber a próxima mensagem, essa mensagem já estará no cache local. O cache deve ser pequeno.
  • Se você estiver usando vários clientes, defina a contagem de pré-busca como 0. Ao definir a contagem, o segundo cliente poderá receber a segunda mensagem enquanto o primeiro cliente ainda estiver processando a primeira mensagem.

Fila com um grande número de remetentes

Meta: maximizar a taxa de transferência de uma fila ou tópico com um grande número de remetentes. Cada remetente envia mensagens com uma taxa moderada. O número de receptores é pequeno.

O Barramento de Serviço permite até 1.000 conexões simultâneas a uma entidade do sistema de mensagens. Esse limite é imposto no nível de namespace e filas, tópicos ou assinaturas são controlados pelo limite de conexões simultâneas por namespace. Para filas, esse número é compartilhado entre remetentes e receptores. Se todas as 1.000 conexões forem obrigatórias para os remetentes, substitua a fila por um tópico e uma assinatura única. Um tópico aceita até 1.000 conexões simultâneas dos remetentes. A assinatura aceita 1.000 conexões simultâneas extras dos receptores. Se mais de 1.000 remetentes simultâneos forem necessários, os remetentes deverão enviar mensagens para o protocolo do Barramento de Serviço via HTTP.

Para maximizar a taxa de transferência, siga estas etapas:

  • Se cada remetente estiver em um processo diferente, use somente uma única fábrica por processo.
  • Defina a contagem de pré-busca como 20 vezes as taxas máximas de processamento de todos os receptores de uma fábrica. Essa contagem reduz o número de transmissões de protocolo de cliente do Barramento de Serviço.

Fila com um grande número de receptores

Meta: maximizar a taxa de recebimento de uma fila ou de uma assinatura com um grande número de receptores. Cada receptor recebe mensagens a uma taxa moderada. O número de remetentes é pequeno.

O Barramento de Serviço permite até 1.000 conexões simultâneas a uma entidade. Se uma fila exigir mais de 1.000 receptores, substitua a fila por um tópico e várias assinaturas. Cada assinatura pode dar suporte a até 1.000 conexões simultâneas. Como alternativa, os receptores poderão acessar a fila por meio do protocolo HTTP.

Para maximizar a taxa de transferência, siga estas diretrizes:

  • Se cada receptor estiver em um processo diferente, use somente uma única fábrica por processo.
  • Defina a contagem de pré-busca como um valor pequeno (por exemplo, PrefetchCount = 10). Essa contagem impede que os receptores fiquem ociosos enquanto outros receptores tenham grandes quantidades de mensagens armazenadas em cache.

Tópico com algumas assinaturas

Meta: maximizar a taxa de transferência de um tópico com poucas assinaturas. Uma mensagem é recebida por muitas assinaturas, o que significa que a taxa de recebimento combinada em todas as assinaturas é maior do que a taxa de envio. O número de remetentes é pequeno. O número de receptores por assinatura é pequeno.

Para maximizar a taxa de transferência, siga estas diretrizes:

  • Para aumentar a taxa geral de envio para o tópico, use diversas fábricas de mensagens para criar remetentes. Para cada remetente, use operações assíncronas ou vários threads.
  • Para aumentar a taxa geral de recebimento de uma assinatura, use diversas fábricas de mensagens para criar receptores. Para cada receptor, use operações assíncronas ou vários threads.
  • Defina a contagem de pré-busca como 20 vezes as taxas máximas de processamento de todos os receptores de uma fábrica. Essa contagem reduz o número de transmissões de protocolo de cliente do Barramento de Serviço.

Tópico com um grande número de assinaturas

Meta: maximizar a taxa de transferência de um tópico com um grande número de assinaturas. Uma mensagem é recebida por muitas assinaturas, o que significa que a taxa de recebimento combinada em todas as assinaturas é maior do que a taxa de envio. O número de remetentes é pequeno. O número de receptores por assinatura é pequeno.

Os tópicos com um grande número de assinaturas normalmente terão uma taxa de transferência geral baixa se todas as mensagens forem roteadas a todas as assinaturas. É porque cada mensagem é recebida várias vezes e todas as mensagens em um tópico e todas as suas assinaturas são armazenadas no mesmo repositório. Supõe-se neste caso que o número de remetentes e o número de receptores por assinatura seja baixo. O Barramento de Serviço dá suporte a até 2.000 assinaturas por tópico.

Para maximizar a taxa de transferência, experimente as etapas a seguir:

  • Defina a contagem de pré-buscas como 20 vezes a taxa esperada na qual as mensagens são recebidas. Essa contagem reduz o número de transmissões de protocolo de cliente do Barramento de Serviço.