Panoramica dell'elaborazione delle transazioni del bus di servizio

Questo articolo descrive le funzionalità delle transazioni del bus di servizio di Microsoft Azure. Gran parte della discussione è illustrata dall'esempio Transazioni. Questo articolo si limita a una panoramica dell'elaborazione delle transazioni e della funzionalità invia tramite nel bus di servizio, invece l'esempio delle transazioni atomiche ha un ambito di riferimento più ampio e complesso.

Nota

  • Il livello basic di bus di servizio non supporta le transazioni. I livelli Standard e Premium supportano le transazioni. Per le differenze tra questi livelli, vedere Prezzi del bus di servizio.
  • La combinazione di operazioni di gestione e messaggistica in una transazione non è supportata.
  • JavaScript SDK non supporta le transazioni.

Transazioni nel bus di servizio

Una transazione raggruppa due o più operazioni in un ambito di esecuzione. Per natura, questo tipo di transazione deve garantire che tutte le operazioni appartenenti a un determinato gruppo di operazioni abbiano esito positivo o negativo. In questo contesto, le transazioni agiscono come unità, spesso definita atomicità.

Il bus di servizio è un gestore di messaggi transazionali e assicura l'integrità transazionale per tutte le operazioni interne eseguite in relazione agli archivi del messaggio. Tutti i trasferimenti di messaggi in bus di servizio, ad esempio lo spostamento di messaggi in una coda di messaggi non recapitabili o l'inoltro automatico dei messaggi tra entità, sono transazionali. Di conseguenza, se il bus di servizio accetta un messaggio, questo è già stato archiviato e contrassegnato con un numero di sequenza. Da questo momento, i trasferimenti di messaggi all'interno del bus di servizio sono operazioni coordinate tra le entità e non causeranno una perdita (l'origine ha esito positivo, mentre la destinazione ha esito negativo) o una duplicazione (l'origine ha esito negativo, mentre la destinazione ha esito positivo) del messaggio.

Il bus di servizio supporta le operazioni di raggruppamento in una singola entità di messaggistica (coda, argomento, sottoscrizione) nell'ambito di una transazione. Ad esempio, è possibile inviare più messaggi a una coda da un ambito di transazione e verrà eseguito il commit dei messaggi al log della coda solo quando la transazione viene completata correttamente.

Operazioni nell'ambito di una transazione

È possibile eseguire le operazioni nell'ambito di una transazione come indicato di seguito:

  • Invia
  • Completo
  • Abbandono
  • Deadletter
  • Rinviare
  • Rinnovare il blocco

Le operazioni di ricezione non sono incluse, perché si presuppone che l'applicazione acquisisca i messaggi usando la modalità di blocco a comparsa, all'interno di un ciclo di ricezione o con un callback e quindi apre solo un ambito di transazione per l'elaborazione del messaggio.

La ricezione del messaggio (completamento, abbandono, non recapitabilità, rinvio) si verifica all'interno dell'ambito e dipende dal risultato complessivo della transazione.

Importante

bus di servizio di Azure non ritenta un'operazione in caso di eccezione quando l'operazione si trova in un ambito di transazione.

Operazioni che non sono incluse negli ambiti delle transazioni

Tenere presente che il codice di elaborazione dei messaggi che chiama nei database e in altri servizi come Cosmos DB non inserisce automaticamente tali risorse downstream nello stesso ambito transazionale. Per altre informazioni su come gestire questi scenari, vedere le linee guida sull'elaborazione dei messaggi idempotenti.

Trasferimenti e "invia tramite"

Per abilitare il passaggio transazionale dei dati da una coda o un argomento a un processore e quindi a un'altra coda o argomento, bus di servizio supporta i trasferimenti. In un'operazione di trasferimento, un mittente invia prima un messaggio a una coda di trasferimento o a un argomento e la coda di trasferimento o l'argomento sposta immediatamente il messaggio nella coda o nell'argomento di destinazione desiderato usando la stessa implementazione di trasferimento affidabile su cui si basa la funzionalità di trasferimento automatico. Il messaggio non viene mai eseguito il commit nella coda di trasferimento o nel log dell'argomento in modo che diventi visibile per i consumer della coda di trasferimento o dell'argomento.

La potenza di questa funzionalità transazionale diventa evidente quando la coda di trasferimento o l'argomento stesso è l'origine dei messaggi di input del mittente. In altre parole, bus di servizio può trasferire il messaggio alla coda di destinazione o all'argomento "tramite" la coda di trasferimento o l'argomento, durante l'esecuzione di un'operazione completa (o rinvia o non recapitabile) sul messaggio di input, tutto in un'unica operazione atomica.

Se è necessario ricevere da una sottoscrizione di un argomento e quindi inviare a una coda o a un argomento nella stessa transazione, l'entità di trasferimento deve essere un argomento. In questo scenario, avviare l'ambito della transazione nell'argomento, ricevere dalla sottoscrizione con nell'ambito della transazione e inviare tramite l'argomento di trasferimento a una coda o a una destinazione dell'argomento.

Nota

Se un messaggio viene inviato tramite una coda di trasferimento nell'ambito di una transazione, TransactionPartitionKey è funzionalmente equivalente a PartitionKey. Garantisce che i messaggi vengano mantenuti insieme e in ordine durante il trasferimento.

Codice di esempio

Per impostare tali trasferimenti, si crea un mittente del messaggio che fa riferimento alla coda di destinazione tramite la coda di trasferimento. È inoltre disponibile un destinatario che estrae i messaggi dalla stessa coda. Ad esempio:

Una transazione semplice usa quindi questi elementi, come nell'esempio seguente. Per fare riferimento all'esempio completo, fare riferimento al codice sorgente in 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();
}

Per altre informazioni sulla EnableCrossEntityTransactions proprietà, vedere il riferimento seguente al metodo ServiceBusClientBuilder.enableCrossEntityTransactions.

Timeout

Timeout di una transazione dopo 2 minuti. Il timer della transazione viene avviato all'avvio della prima operazione nella transazione.

Passaggi successivi

Per altre informazioni sulle code bus di servizio, vedere gli articoli seguenti: