Compartilhar via


Filas e tópicos particionados

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

Observação

Há algumas diferenças entre o SKU Básico/Standard e Premium quando se trata de particionamento.

  • Particionar está disponível na criação da identidade para todas as filas e tópicos em SKUs Básico ou Standard. Um namespace pode ter entidades particionadas e não particionadas.
  • O particionamento está disponível na criação do namespace para o SKU de mensagens Premium e todas as filas e tópicos nesse namespace são particionados. Todas as entidades particionadas migradas anteriormente em namespaces Premium continuam funcionando conforme o esperado.
  • Ao habilitar o particionamento nos SKUs Básico ou Standard, você sempre cria 16 partições.
  • Ao habilitar o particionamento no SKU Premium, especifique o número de partições durante a criação do namespace.

Não é possível alterar a opção de particionamento em qualquer namespace, fila ou tópico existente. Você só pode definir a opção ao criar a entidade.

Como ele funciona

Cada fila ou tópico particionado consiste em várias partições. Cada partição é armazenada em um repositório de mensagens diferente e processada por um agente de mensagens diferente. Quando você envia uma mensagem para uma fila ou tópico particionado, o Service Bus atribui a mensagem a uma das partições. O Barramento de Serviço seleciona a partição aleatoriamente ou usa uma chave de partição especificada pelo remetente.

Quando um cliente deseja receber uma mensagem de uma fila particionada ou de uma assinatura para um tópico particionado, o Barramento de Serviço consulta todas as partições de mensagens. Ele retorna a primeira mensagem que recebe de qualquer um dos repositórios de mensagens para o receptor. O Service Bus armazena em cache as outras mensagens e as retorna quando recebe mais solicitações. Um cliente receptor não está ciente do particionamento. O comportamento voltado para o cliente de uma fila ou tópico particionado (por exemplo, ler, preencher, adiar, colocar mensagem na fila de mensagens mortas, pré-buscar) é 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 isso não ocorre em uma entidade particionada. Em vez disso, ele exibe a mensagem mais antiga em uma das partições cujo agente de mensagens respondeu primeiro. Não há garantias de que a mensagem exibida seja a mais antiga de todas as partições.

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

Observação

A operação de inspeção exibe a mensagem mais antiga da partição com base no número sequencial dela. Para entidades particionadas, o número de sequência é relativo à partição. Para mais informações, confira Sequenciamento e registros de data e hora das mensagens.

Uso de chaves de partição

Quando você enfileira uma mensagem em uma fila ou tópico particionado, o Barramento de Serviço verifica a presença de uma chave de partição. Se ele encontrar uma chave, escolherá a partição com base nela. Se ele não encontrar uma chave de partição, escolherá a partição com base em um 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, propriedades de mensagem diferentes são usadas como uma chave de partição:

SessionId: Se uma mensagem tiver a propriedade SessionId definida, o Service Bus usará isso como a chave de partição. Dessa forma, o mesmo agente de mensagens manipula todas as mensagens que pertencem à mesma sessão. Ao usar sessões, o Barramento de Serviço garante a ordenação das mensagens e a consistência dos estados de sessão.

PartitionKey: caso uma mensagem tenha a propriedade da chave de partição definida, mas não a propriedade de ID da sessão, o Barramento de Serviço usará o valor da propriedade da chave de partição como a chave de partição. Caso a mensagem tenha as propriedades de ID da sessão e da chave de partição definidas, as propriedades deverão ser idênticas. Se a propriedade da chave de partição for definida com um valor diferente da propriedade de 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 sem reconhecimento de sessão. A chave de partição garante que o mesmo agente de mensagens manipule todas as mensagens enviadas dentro de uma transação.

MessageId: se você criar a fila ou o tópico com o recurso de detecção duplicada e não definir a ID da sessão ou as propriedades da chave de partição, o valor da propriedade ID da mensagem servirá como a chave de partição. (As bibliotecas de clientes da Microsoft atribuem automaticamente uma ID de mensagem se o aplicativo de envio não o fizer.) Nesse caso, o mesmo agente de mensagens manipula todas as cópias da mesma mensagem. Este ID permite que o Barramento de Serviço detecte e elimine mensagens duplicadas. Se o recurso de detecção de duplicidades não estiver habilitado, o Barramento de Serviço não considerará a propriedade ID da mensagem como uma chave de partição.

Não usando uma chave de partição

Se você não especificar uma chave de partição, o Barramento de Serviço distribuirá mensagens em forma de round robin para todas as partições da fila ou do 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 será bem-sucedida independentemente da indisponibilidade temporária de um repositório de mensagens. No entanto, você não obtém a ordenação garantida que uma chave de partição fornece.

Para obter uma discussão mais detalhada sobre a compensação entre disponibilidade (sem chave de partição) e consistência (usando uma chave de partição), confira Disponibilidade e consistência no Hubs de Eventos. Exceto que a ID de partição não esteja sendo exposta aos usuários, essas informações se aplicam igualmente a entidades de Barramento de Serviço particionadas.

Para dar ao Barramento de Serviço tempo suficiente para enfileirar a mensagem em uma partição diferente, o valor de tempo de 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 em uma partição específica. Se o repositório de mensagens que mantém essa partição estiver indisponível, o Barramento de Serviço exibirá um erro. Na ausência de uma chave de partição, o Barramento de Serviço pode escolher uma partição diferente e a operação será bem-sucedida. Portanto, não forneça uma chave de partição, a menos que seja necessária.

Tópicos avançados

Usar transações com entidades particionadas

As mensagens enviadas 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 enviadas como parte da mesma transação devem especificar a mesma chave de partição. Caso você tente 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. Caso você tente enviar várias mensagens que tenham chaves de partição diferentes na mesma transação, o Barramento de Serviço 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 você definir qualquer uma das propriedades que servem como chave de partição, o Service Bus aloca a mensagem a uma partição específica. Esse comportamento ocorre se você usa ou não uma transação. Não especifique uma chave de partição se ela não for necessária.

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

Para enviar uma mensagem transacional para um tópico ou fila com reconhecimento de sessão, defina a propriedade ID da sessão na mensagem. Se você especificar a propriedade de chave de partição, ela deverá ser idêntica à propriedade de ID da sessão. Caso elas sejam diferentes, o Barramento de Serviço retornará uma exceção de operação inválida.

Ao contrário de filas ou tópicos regulares (não particionados), você não pode usar uma única transação para enviar várias mensagens para sessões diferentes. Se você tentar essa operação, o Barramento de Serviço 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.SessionId = "mySession";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

Encaminhamento automático de mensagens com entidades particionadas

O Service Bus dá 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 saber mais, confira Habilitar encaminhamento de mensagens. Se a mensagem especificar uma chave de partição (ID da sessão, chave de partição ou ID da mensagem), essa chave de partição será usada para a entidade de destino.

Considerações e diretrizes

  • Recursos de alta consistência: se uma entidade usa recursos como sessões, detecção duplicada ou controle explícito da chave de particionamento, as operações de mensagens sempre roteiam para uma partição específica. Se alguma das partições apresentar alto tráfego ou se o repositório subjacente não estiver íntegro, essas operações apresentarão falha e a disponibilidade será reduzida. No geral, a consistência ainda é muito maior do que as entidades não particionadas. Apenas um subconjunto de tráfego enfrenta problemas, em oposição a 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 íntegra, isso poderá resultar na falha dessas operações. Para a operação Get, informações como números de mensagens devem ser agregadas de todas as partições. Se alguma partição estiver com problemas, o status de disponibilidade da entidade será informado como sendo limitado.
  • Cenários de mensagens de baixo volume: para esses cenários, particularmente ao usar o protocolo HTTP, talvez você precise executar várias operações de recebimento para obter todas as mensagens. Para solicitações de recebimento, o front-end executa um recebimento em todas as partições e armazena em cache todas as respostas recebidas. Uma solicitação de recebimento subsequente na mesma conexão se beneficia desse cache, e as latências de recebimento são menores. No entanto, se você tiver várias conexões ou se usar HTTP, uma nova conexão será estabelecida para cada solicitação. Assim, não há garantia de que ela chegará ao mesmo nó. Se todas as mensagens existentes forem bloqueadas e armazenadas em cache no outro front-end, a operação de recebimento resultará em nulo. As mensagens eventualmente expiram e você pode recebê-las novamente. O keep-alive do HTTP é recomendado. Ao usar o particionamento em cenários de baixo volume, as operações de recebimento podem demorar mais tempo que o esperado. Portanto, não use particionamento nesses cenários. Exclua todas as entidades particionadas existentes e recrie-as com o particionamento desabilitado para melhorar o desempenho.
  • Procurar/espiar mensagens: a operação de espiar nem sempre retorna o número de mensagens solicitado. Dois motivos comuns explicam esse comportamento. Uma razão é que o tamanho agregado da coleção de mensagens excede o tamanho máximo. Outro motivo é que, em filas ou tópicos particionados, uma partição pode não ter mensagens suficientes para retornar o número solicitado de mensagens. Em geral, se um aplicativo quiser espiar ou procurar um número específico de mensagens, ele deverá chamar a operação de espiada repetidamente até obter esse número de mensagens ou não houver mais mensagens para espiar. Para saber mais, incluindo exemplos de código, confira Navegação de mensagens.

Limitações das entidades particionadas

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

  • Filas e tópicos particionados não dão suporte ao envio de mensagens que pertencem a sessões diferentes em uma única transação.
  • Atualmente, o Barramento de Serviço permite até 100 filas ou tópicos particionados por namespace para os níveis Básico e Padrão. Cada fila ou tópico particionado conta para a cota de 10.000 entidades por namespace.

Próximas etapas

Você pode habilitar o particionamento usando o portal do Azure, PowerShell, CLI, modelo do Gerenciador de Recursos, .NET, Java, Python e JavaScript. Para saber mais, confira Habilitar o particionamento (Básico / Standard).

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