Partilhar via


Filas e tópicos particionados

O Azure Service Bus utiliza múltiplos intermediários de mensagens para processar mensagens e múltiplos repositórios de mensagens para armazenar mensagens. Uma fila ou tópico convencional é tratado por um único corretor de mensagens e uma loja de mensagens. As partições do Barramento de Serviço permitem que filas e tópicos, ou entidades de mensagens, sejam particionados em vários brokers de mensagens e repositórios de mensagens. O particionamento significa que a taxa de transferência geral de uma entidade particionada não é mais limitada pelo desempenho de um único agente de mensagens ou armazenamento de mensagens. Além disso, uma interrupção temporária de uma loja de mensagens não torna uma fila ou tópico particionado indisponível. Filas e tópicos particionados podem conter todos os recursos avançados do Service Bus, como suporte para transações e sessões.

Nota

Existem algumas diferenças entre o Basic / Standard e Premium SKU quando se trata de particionamento.

  • O particionamento está disponível na criação de entidades para todas as filas e tópicos em SKUs Básico ou Padrão. Um namespace pode ter entidades particionadas e não particionadas.
  • A partição está disponível na criação do namespace para o SKU de mensagens Premium, e todas as filas e tópicos desse namespace estão particionados. Quaisquer entidades particionadas previamente migradas em namespaces Premium continuam a funcionar como esperado.
  • Quando ativas a partição nos SKUs Basic ou Standard, crias sempre 16 partições.
  • Quando ativas a partição no SKU Premium, especificas o número de partições durante a criação do namespace.

Não podes alterar a opção de particionamento em qualquer namespace, fila ou tópico existente. Só podes definir essa opção quando criares a entidade.

Como funciona

Cada fila ou tópico particionado consiste em várias partições. Cada partição é armazenada em um armazenamento de mensagens diferente e manipulada por um agente de mensagens diferente. Quando envia uma mensagem para uma fila ou tópico particionado, o Service Bus atribui a mensagem a uma das partições. O Service Bus seleciona a partição aleatoriamente ou usa uma chave de partição que o emissor especifica.

Quando um cliente quer receber uma mensagem de uma fila particionada, ou de uma subscrição a um tópico particionado, o Service Bus consulta todas as partições para obter mensagens. Devolve a primeira mensagem que recebe de qualquer loja de mensagens ao destinatário. O Barramento de Serviço armazena em cache as outras mensagens e as retorna quando recebe mais pedidos de receção. Um cliente recetor não está ciente da partição. O comportamento voltado para o cliente de uma fila ou tópico particionado, como leitura, finalização, adiamento, envio para caixa de não entrega e pré-busca, é idêntico ao comportamento de uma entidade regular.

A operação de visualização em uma entidade não particionada sempre retorna a mensagem mais antiga, mas não em uma entidade particionada. Em vez disso, ele retorna a mensagem mais antiga em uma das partições cujo agente de mensagens respondeu primeiro. Não há garantia de que a mensagem retornada seja a mais antiga em todas as partições.

Não há custo extra ao enviar ou receber uma mensagem de uma fila ou tópico particionado.

Nota

A operação peek retorna a mensagem mais antiga da partição com base em seu número de sequência. Para entidades particionadas, o número de sequência é relativo à partição. Para obter mais informações, consulte Carimbos de data/hora e sequenciamento de mensagens.

Utilização de chaves de partição

Quando colocas uma mensagem numa fila ou tópico particionado, o Service Bus verifica a presença de uma chave de partição. Se encontrar uma, seleciona a partição com base nessa chave. Se não encontrar uma chave de partição, seleciona a partição com base num algoritmo interno.

Usando uma chave de partição

Alguns cenários, como sessões ou transações, exigem que as mensagens sejam armazenadas em uma partição específica. Todos esses cenários exigem o uso de uma chave de partição. O Service Bus atribui todas as mensagens que usam a mesma chave de partição à mesma partição. Se a partição estiver temporariamente indisponível, o Service Bus retornará um erro.

Dependendo do cenário, diferentes propriedades de mensagem são usadas como uma chave de partição:

SessionId: Se uma mensagem tiver a propriedade ID de sessão definida, o Service Bus usa-a como chave de partição. Desta forma, o mesmo broker de mensagens trata todas as mensagens que pertencem à mesma sessão. Ao utilizar sessões, o Service Bus garante a ordenação das mensagens, bem como a consistência dos estados da sessão.

PartitionKey: Se uma mensagem tiver a propriedade de chave de partição mas não o conjunto de propriedades ID de sessão, o Service Bus usa o valor da propriedade chave de partição como chave de partição. Se a mensagem tiver o ID da sessão e as propriedades da chave de partição definidas, ambas as propriedades deverão ser idênticas. Se a propriedade da chave de partição estiver definida com um valor diferente da propriedade ID da sessão, o Service Bus retornará uma exceção de operação inválida. Use a propriedade de chave de partição se um remetente enviar mensagens transacionais não conscientes da sessão. A chave de partição garante que o mesmo broker de mensagens trata todas as mensagens enviadas dentro de uma transação.

MessageId: Se criares a fila ou tópico com a funcionalidade de deteção de duplicados e não definires as propriedades do ID da sessão ou da chave de partição, o valor da propriedade ID da mensagem serve como chave de partição. (As bibliotecas clientes da Microsoft atribuem automaticamente um ID de mensagem se a aplicação de envio não o fizer.) Neste caso, o mesmo corretor de mensagens trata de todas as cópias da mesma mensagem. Essa ID permite que o Service Bus detete e elimine mensagens duplicadas. Se o recurso de deteção de duplicados não estiver habilitado, o Service Bus não considerará a propriedade ID da mensagem como uma chave de partição.

Não usar uma chave de partição

Se não especificar uma chave de partição, o Service Bus distribui as mensagens de forma round-robin para todas as partições da fila ou tópico particionado. Se a partição escolhida não estiver disponível, o Service Bus atribuirá a mensagem a uma partição diferente. Dessa forma, a operação de envio é bem-sucedida apesar da indisponibilidade temporária de um armazenamento de mensagens. No entanto, não consegues a ordem garantida que uma chave de partição oferece.

Para obter uma discussão mais aprofundada sobre a compensação entre disponibilidade (sem chave de partição) e consistência (usando uma chave de partição), consulte Disponibilidade e consistência em Hubs de Eventos. Exceto para o ID de partição não ser exposto aos usuários, essas informações se aplicam igualmente a entidades particionadas do Service Bus.

Para dar ao Service Bus tempo suficiente para enfileirar a mensagem em uma partição diferente, o valor de tempo limite especificado pelo cliente que envia a mensagem deve ser maior que 15 segundos. O valor padrão de 60 segundos é recomendado.

Uma chave de partição "fixa" uma mensagem a uma partição específica. Se o armazenamento de mensagens que contém essa partição não estiver disponível, o Service Bus retornará um erro. Na ausência de uma chave de partição, o Service Bus pode escolher uma partição diferente e a operação é bem-sucedida. Por isso, não forneça uma chave de partição a menos que seja necessário.

Tópicos avançados

Usar transações com entidades particionadas

As mensagens que envia como parte de uma transação devem especificar uma chave de partição. A chave pode ser uma das seguintes propriedades: ID da sessão, chave de partição ou ID da mensagem. Todas as mensagens que envia como parte da mesma transação devem especificar a mesma chave de partição. Se você tentar enviar uma mensagem sem uma chave de partição dentro de uma transação, o Service Bus retornará uma exceção de operação inválida. Se você tentar enviar várias mensagens dentro da mesma transação que tenham chaves de partição diferentes, o Service Bus retornará uma exceção de operação inválida. Por exemplo:

CommittableTransaction committableTransaction = new CommittableTransaction();
using (TransactionScope ts = new TransactionScope(committableTransaction))
{
    ServiceBusMessage msg = new ServiceBusMessage("This is a message");
    msg.PartitionKey = "myPartitionKey";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

Se definires alguma das propriedades que servem como chave de partição, o Service Bus fixa a mensagem numa partição específica. Este comportamento ocorre quer use ou não uma transação. Não especifiquem uma chave de partição se não for necessário.

Usar transações em sessões com entidades particionadas

Para enviar uma mensagem transacional para um tópico ou fila compatível com sessões, defina a propriedade ID da sessão na mensagem. Se especificar a propriedade da chave de partição, ela deve ser idêntica à propriedade do ID da sessão. Se forem diferentes, o Service Bus retornará uma exceção de operação inválida.

Ao contrário das filas ou tópicos normais (não particionados), não podes usar uma única transação para enviar múltiplas mensagens para diferentes sessões. Se tentar esta operação, o Service Bus devolve uma exceção de operação inválida. Por exemplo:

CommittableTransaction committableTransaction = new CommittableTransaction();
using (TransactionScope ts = new TransactionScope(committableTransaction))
{
    ServiceBusMessage msg = new ServiceBusMessage("This is a message");
    msg.SessionId = "mySession";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

Reencaminhamento automático de mensagens com entidades particionadas

O Service Bus oferece suporte ao encaminhamento automático de mensagens de, para ou entre entidades particionadas. Você pode habilitar esse recurso ao criar ou atualizar filas e assinaturas. Para obter mais informações, consulte Habilitar o encaminhamento de mensagens. Se a mensagem especificar uma chave de partição (ID de sessão, chave de partição ou ID de mensagem), essa chave de partição é usada para a entidade de destino.

Considerações e orientações

  • Funcionalidades de alta consistência: Se uma entidade usar funcionalidades como sessões, deteção de duplicados ou controlo explícito da chave de partição, então as operações de mensagens são sempre encaminhadas para uma partição específica. Se qualquer uma das partições tiver alto tráfego ou o armazenamento subjacente não estiver íntegro, essas operações falharão e a disponibilidade será reduzida. No geral, a consistência continua a ser muito superior à das entidades não particionadas. Apenas um subconjunto do trânsito tem problemas, ao contrário de todo o tráfego. Para obter mais informações, consulte esta discussão sobre disponibilidade e consistência.
  • Gerenciamento: Operações como Criar, Atualizar e Excluir devem ser executadas em todas as partições da entidade. Se alguma partição não estiver saudável, isso pode resultar em falhas para essas operações. Para a operação Get, informações como contagens de mensagens devem ser agregadas de todas as partições. Se alguma partição não estiver saudável, o estado de disponibilidade da entidade será reportado como limitado.
  • Cenários de mensagens de baixo volume: Para esses cenários, especialmente ao usar o protocolo HTTP, talvez seja necessário executar várias operações de recebimento para obter todas as mensagens. Para pedidos de receção, a interface realiza uma receção em todas as partições e armazena em cache todas as respostas que recebe. Um pedido de receção subsequente na mesma ligação beneficia desta cache e as latências de receção são menores. No entanto, se você tiver várias conexões ou usar HTTP, uma nova conexão será estabelecida para cada solicitação. Assim, não há garantia de que caia no mesmo nó. Se todas as mensagens existentes estiverem bloqueadas e armazenadas em cache em outro front-end, a operação de recebimento retornará null. As mensagens eventualmente expiram e você pode recebê-las novamente. HTTP keep-alive é recomendado. Ao usar o particionamento em cenários de baixo volume, as operações de recebimento podem levar mais tempo do que o esperado. Por isso, não uses partição nestes cenários. Exclua todas as entidades particionadas existentes e recrie-as com o particionamento desativado para melhorar o desempenho.
  • Procurar/Espreitar mensagens: A operação de pré-visualização nem sempre devolve o número de mensagens solicitadas. Duas razões comuns explicam este comportamento. Uma razão é que o tamanho agregado da coleção de mensagens excede o tamanho máximo. Outra razão é que, em filas ou tópicos particionados, pode não haver mensagens suficientes numa partição para devolver o número solicitado de mensagens. Em geral, se uma aplicação quiser espreitar ou navegar por um número específico de mensagens, deve chamar repetidamente a operação de espreitar até obter esse número de mensagens ou até não haver mais mensagens para espreitar. Para obter mais informações, incluindo exemplos de código, consulte Navegação por mensagens.

Limitações de entidades particionadas

Atualmente, o Service Bus impõe as seguintes limitações a filas e tópicos particionados:

  • Filas e tópicos particionados não suportam o envio de mensagens que pertencem a sessões diferentes em uma única transação.
  • Atualmente, o Service Bus permite até 100 filas ou tópicos particionados por namespace para os níveis Basic e Standard. Cada fila ou tópico particionado contribui para a cota de 10.000 entidades por namespace.

Próximos passos

Você pode habilitar o particionamento usando o portal do Azure, PowerShell, CLI, modelo do Gerenciador de Recursos, .NET, Java, Python e JavaScript. Para obter mais informações, consulte Habilitar particionamento (básico / padrão).

Para aprender sobre os conceitos centrais da especificação de mensagens do Advanced Message Queuing Protocol (AMQP) 1.0, consulte o guia do protocolo AMQP 1.0.