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 si basa sull'esempio delle 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 del 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 all'interno del Bus di servizio, ad esempio lo spostamento di messaggi a una coda dei messaggi non recapitabili o all'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:

  • Send
  • Completo
  • Abbandono
  • Inserire nella coda di messaggi non recapitabili
  • Rinvia
  • Rinnovare il blocco

Le operazioni di ricezione non sono incluse perché si presuppone che l'applicazione acquisisca i messaggi usando la modalità peek-lock, all'interno di alcuni cicli di ricezione o di un callback, e solo successivamente apra 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

Il 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 idempotent.

Trasferimenti e "invia tramite"

Per abilitare il passaggio transazionale dei dati da una coda o un argomento a un processore e successivamente a un'altra coda o argomento, il Bus di servizio supporta i trasferimenti. In un'operazione di trasferimento un mittente invia un messaggio a una coda o argomento di trasferimento e la coda o l'argomento sposta immediatamente il messaggio alla coda all'argomento di destinazione prestabilito usando la stessa implementazione di trasferimento affidabile su cui si basa la funzionalità di inoltro automatico. Non viene mai eseguito il commit del messaggio al log della coda o dell'argomento di trasferimento in modo che diventi visibile agli utenti della coda o dell'argomento di trasferimento.

L'efficacia di questa funzionalità transazionale diventa evidente quando la coda di trasferimento o l'argomento stesso è l'origine dei messaggi di input del mittente. In altri termini, il Bus di servizio può trasferire il messaggio alla coda di destinazione o argomento "tramite" la coda di trasferimento o argomento, durante l'esecuzione di un'operazione di completamento (o rinvio o inserimento nei messaggi non recapitabili) nel messaggio di input, il tutto in una singola 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.
  • Se la coda o l'argomento di destinazione viene eliminata, viene generata un'eccezione 404.

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 questi elementi, come nell'esempio seguente. Per fare riferimento all'esempio completo, vedere il 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 proprietà EnableCrossEntityTransactions, vedere il riferimento seguente 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 del bus di servizio, vedere gli articoli seguenti: