Visão geral do processamento de transações do Barramento de Serviço

Este artigo aborda as funcionalidades de transação do Barramento de Serviço do Microsoft Azure. Grande parte da discussão é ilustrada pelo Exemplo de transações. Este artigo é limitado a uma visão geral do processamento de transações e ao recurso Enviar por do Barramento de Serviço, enquanto a amostra Transações atômicas tem um escopo mais amplo e complexo.

Observação

  • A camada básica do Barramento de Serviço não dá suporte a transações. As camadas Standard e Premium dão suporte a transações. Para conferir as diferenças entre essas camadas, consulte preços do Barramento de Serviço.
  • Não há suporte para a combinação de operações de gerenciamento e mensagens em uma transação.
  • O SDK do JavaScript não tem suporte para transações.

Transações no Barramento de Serviço

Uma transação agrupa duas ou mais operações em um escopo de execução. Por natureza, essa transação deve garantir que todas as operações que pertencem a determinado grupo de operações sejam concluídas com êxito ou com falha em conjunto. Nesse sentido, as transações agem como uma unidade, que, geralmente, é conhecida como atomicidade.

O Barramento de Serviço é um agente de mensagens transacionais e assegura a integridade transacional de todas as operações internas em seus repositórios de mensagens. Todas as transferências de mensagens no Barramento de Serviço, como a movimentação de mensagens para uma fila de mensagens mortas ou encaminhamento automático de mensagens entre entidades, são transacionais. Assim, caso o Barramento de Serviço aceite uma mensagem, isso significa ela já foi armazenada e rotulada com um número de sequência. Daí em diante, todas as transferências de mensagens no Barramento de Serviço são operações coordenadas entre entidades e não resultarão em perda (origem com êxito e destino com falha) nem em duplicação (origem com falha e destino com êxito) da mensagem.

O Barramento de Serviço dá suporte a operações de agrupamento em uma única entidade de mensagens (fila, tópico e assinatura) no escopo de uma transação. Por exemplo, você pode enviar várias mensagens para uma fila em um escopo de transação, e as mensagens só serão confirmadas no log da fila quando a transação for concluída com êxito.

Operações em um escopo de transação

As operações que podem ser executadas em um escopo de transação são as seguintes:

  • Enviar
  • Concluir
  • Abandonar
  • Mensagens mortas
  • Adiar
  • Renovar bloqueio

As operações de recebimento não são incluídas, pois presume-se que o aplicativo obtenha as mensagens usando o modo bloqueio de inspeção em algum loop de recebimento ou com um retorno de chamada, e só então abre um escopo de transação para o processamento da mensagem.

Em seguida, a disposição da mensagem (conclusão, abandono, mensagens mortas, adiamento) ocorre no escopo do resultado geral da transação e depende dele.

Importante

O Barramento de Serviço do Azure não repetirá uma operação no caso de uma exceção quando a operação estiver em um escopo de transação.

Operações que não se inscrevem em escopos de transação

Lembre-se de que o código de processamento de mensagens que chama bancos de dados e outros serviços, como o Cosmos DB, não inscreve automaticamente esses recursos downstream no mesmo escopo transacional. Para obter mais informações sobre como lidar com esses cenários, examine as diretrizes sobre o processamento de mensagens idempotentes.

Transferências e “enviar por”

Para habilitar a transferência transacional dos dados de uma fila ou tópico para um processador e, em seguida, para outra fila ou tópico, o Barramento de Serviço dá suporte a transferências. Em uma operação de transferência, um remetente primeiro envia uma mensagem para uma fila ou tópico de transferência e a fila ou tópico de transferência move imediatamente a mensagem para a fila ou tópico de destino desejado usando a mesma implementação de transferência robusta da qual a funcionalidade de encaminhamento automático depende. A mensagem nunca é confirmada para a fila de transferência ou o log do tópico de modo que se torne visível para os consumidores da fila de transferência ou do tópico.

A potência dessa funcionalidade transacional se torna aparente quando a própria fila ou tópico de transferência é a origem das mensagens de entrada do remetente. Em outras palavras, o Barramento de Serviço pode transferir a mensagem para a fila ou tópico de destino por meio da fila ou tópico de transferência, ao mesmo tempo que executa uma operação de conclusão (ou adiamento ou mensagens mortas) nas mensagens de entrada, tudo em uma única operação atômica.

Se você precisar receber de uma assinatura de tópico e, em seguida, enviar para uma fila ou tópico na mesma transação, a entidade de transferência deverá ser um tópico. Nesse cenário, inicie o escopo da transação no tópico, receba da assinatura no escopo da transação e envie através do tópico de transferência para um destino de fila ou tópico.

Observação

Se uma mensagem for enviada por meio de uma fila de transferência no escopo de uma transação, TransactionPartitionKey será funcionalmente equivalente a PartitionKey. Ele garante que as mensagens sejam mantidas juntas e em ordem à medida que são transferidas.

Ver em código

Para configurar essas transferências, você cria um remetente da mensagem que tem como alvo a fila de destino por meio da fila de transferência. Você também terá um receptor que fará o pull das mensagens dessa mesma fila. Por exemplo:

Uma transação simples usa então esses elementos, como mostrado no exemplo a seguir. Para consultar o exemplo completo, consulte o código-fonte no GitHub:

var options = new ServiceBusClientOptions { EnableCrossEntityTransactions = true };
await using var client = new ServiceBusClient(connectionString, options);

ServiceBusReceiver receiverA = client.CreateReceiver("queueA");
ServiceBusSender senderB = client.CreateSender("queueB");

ServiceBusReceivedMessage receivedMessage = await receiverA.ReceiveMessageAsync();

using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
    await receiverA.CompleteMessageAsync(receivedMessage);
    await senderB.SendMessageAsync(new ServiceBusMessage());
    ts.Complete();
}

Para saber mais sobre a propriedade EnableCrossEntityTransactions, consulte seguinte Método ServiceBusClientBuilder.enableCrossEntityTransactions de referência.

Tempo limite

Uma transação atinge o tempo limite após 2 minutos. O temporizador da transação é iniciado quando a primeira operação na transação é iniciada.

Próximas etapas

Para obter mais informações sobre as filas do Barramento de Serviço, confira os artigos a seguir: