Esercizio - Inviare e ricevere messaggi usando un argomento
Si è deciso di usare un argomento del bus di servizio di Azure per distribuire i messaggi relativi all'andamento delle vendite nell'applicazione degli addetti alle vendite. Il personale di vendita userà l'app sui propri dispositivi mobili per inviare messaggi che riassumono i dati di vendita per ogni area e periodo di tempo. Questi messaggi saranno distribuiti ai servizi Web situati nelle aree operative dell'azienda, comprese le Americhe e l'Europa.
È già stata implementata l'infrastruttura necessaria nelle sottoscrizioni di Azure per l'argomento. Ora si vuole scrivere il codice che invia messaggi all'argomento e il codice che recupera i messaggi da una sottoscrizione. Si invia quindi un messaggio a un argomento e si recupera il messaggio per una sottoscrizione specifica.
Verificare di trovarsi nella directory corretta eseguendo i comandi seguenti in Azure Cloud Shell:
cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
code .
Scrivere il codice per inviare un messaggio a un argomento
Per completare il componente che invia messaggi sull'andamento delle vendite, seguire questa procedura:
Nell'editor di Azure Cloud Shell aprire performancemessagesender/Program.cs e individuare la riga di codice seguente:
const string ServiceBusConnectionString = "";
Incollare la stringa di connessione salvata nell'esercizio precedente tra virgolette.
Se è stato usato un nome diverso da salesperformancemessages per il nome della coda, aggiornare il valore per la proprietà
TopicName
nel codice:const string TopicName = "salesperformancemessages";
Trovare il metodo
SendPerformanceMessageAsync()
. (Suggerimento: si trova alla riga 26 o vicino a essa). All'interno di questo metodo, individuare la riga di codice seguente:// Create a Service Bus client here
Sostituire la riga di codice con quella seguente:
// By leveraging "await using", the DisposeAsync method will be called automatically when the client variable goes out of scope. // In more realistic scenarios, you would store off a class reference to the client (rather than to a local variable) so that it can be used throughout your program. await using var client = new ServiceBusClient(ServiceBusConnectionString);
All'interno del metodo
SendPerformanceMessageAsync()
individuare la riga di codice seguente:// Create a sender here
Sostituire la riga di codice con quella seguente:
await using ServiceBusSender sender = client.CreateSender(TopicName);
Nel blocco
try...catch
individuare la riga di codice seguente:// Create and send a message here
Sostituire la riga di codice con quella seguente:
string messageBody = "Total sales for Brazil in August: $13m."; var message = new ServiceBusMessage(messageBody);
Per visualizzare il messaggio nella console, inserire il codice seguente nella riga successiva:
Console.WriteLine($"Sending message: {messageBody}");
Per inviare il messaggio all'argomento, inserire il codice seguente nella riga successiva:
await sender.SendMessageAsync(message);
Verificare che il codice finale sia simile all'esempio seguente:
using System; using System.Threading.Tasks; using Azure.Messaging.ServiceBus; namespace performancemessagesender { class Program { const string ServiceBusConnectionString = "Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx"; const string TopicName = "salesperformancemessages"; static void Main(string[] args) { Console.WriteLine("Sending a message to the Sales Performance topic..."); SendPerformanceMessageAsync().GetAwaiter().GetResult(); Console.WriteLine("Message was sent successfully."); } static async Task SendPerformanceMessageAsync() { // By leveraging "await using", the DisposeAsync method will be called automatically once the client variable goes out of scope. // In more realistic scenarios, you would store off a class reference to the client (rather than to a local variable) so that it can be used throughout your program. await using var client = new ServiceBusClient(ServiceBusConnectionString); await using ServiceBusSender sender = client.CreateSender(TopicName); try { string messageBody = "Total sales for Brazil in August: $13m."; var message = new ServiceBusMessage(messageBody); Console.WriteLine($"Sending message: {messageBody}"); await sender.SendMessageAsync(message); } catch (Exception exception) { Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}"); } } } }
Per salvare le modifiche, premere CTRL+S e quindi CTRL+Q per chiudere l'editor.
Inviare un messaggio all'argomento
Per eseguire il componente che invia un messaggio su una vendita, immettere il comando seguente in Cloud Shell:
dotnet run --project performancemessagesender
Durante l'esecuzione del programma, controllare le notifiche di Cloud Shell che indicano l'avvenuto invio di un messaggio. Ogni volta che si esegue l'app, un altro messaggio viene aggiunto all'argomento e una copia diventa disponibile per ogni sottoscrizione.
Sending a message to the Sales Performance topic... Sending message: Total sales for Brazil in August: $13m. Message was sent successfully.
Controllare il numero dei messaggi prima di recuperarli per una sottoscrizione
Quando viene visualizzato il testo Message was sent successfully
, eseguire il comando seguente per vedere quanti messaggi si trovano nella sottoscrizione Americas
. Ricordare di sostituire <namespace-name> con lo spazio dei nomi del bus di servizio.
az servicebus topic subscription show \
--resource-group "<rgn>[sandbox resource group name]</rgn>" \
--topic-name salesperformancemessages \
--name Americas \
--query messageCount \
--namespace-name <namespace-name>
Se si sostituisce Americas
con EuropeAndAsia
e si esegue di nuovo il comando, si noterà che entrambe le sottoscrizioni hanno lo stesso numero di messaggi.
Scrivere il codice per recuperare un messaggio dell'argomento per una sottoscrizione
Per creare il componente che recupera i messaggi sull'andamento delle vendite, seguire questa procedura:
Eseguire
code .
per avviare l'editor.Nell'editor aprire performancemessagereceiver/Program.cs e individuare la riga di codice seguente:
const string ServiceBusConnectionString = "";
Incollare la stringa di connessione salvata nell'esercizio precedente tra virgolette.
Per creare un client del bus di servizio, individuare il metodo
MainAsync()
. All'interno di questo metodo individuare la riga di codice seguente:// Create a Service Bus client that will authenticate using a connection string
Sostituire la riga con il codice seguente:
var client = new ServiceBusClient(ServiceBusConnectionString);
Per configurare le opzioni di gestione dei messaggi, individuare la riga di codice seguente:
// Create the options to use for configuring the processor
Sostituire la riga con il codice seguente:
var processorOptions = new ServiceBusProcessorOptions { MaxConcurrentCalls = 1, AutoCompleteMessages = false };
Per creare un processore, individuare la riga di codice seguente:
// Create a processor that we can use to process the messages
Sostituire la riga con il codice seguente:
ServiceBusProcessor processor = client.CreateProcessor(TopicName, SubscriptionName, processorOptions);
Per configurare il gestore, individuare la riga di codice seguente:
// Configure the message and error handler to use
Sostituire la riga con il codice seguente:
processor.ProcessMessageAsync += MessageHandler; processor.ProcessErrorAsync += ErrorHandler;
Per avviare l'elaborazione, individuare la riga di codice seguente:
// Start processing
Sostituire la riga con il codice seguente:
await processor.StartProcessingAsync();
Cercare la riga di codice seguente:
// Since we didn't use the "await using" syntax here, we need to explicitly dispose the processor and client
Sostituire la riga con il codice seguente:
await processor.DisposeAsync(); await client.DisposeAsync();
Per visualizzare i messaggi in arrivo nella console, individuare il metodo
MessageHandler()
. Questo metodo è stato registrato per gestire i messaggi in arrivo.Sostituire tutto il codice all'interno del metodo con quello seguente:
Console.WriteLine($"Received message: SequenceNumber:{args.Message.SequenceNumber} Body:{args.Message.Body}");
Per rimuovere il messaggio ricevuto dalla sottoscrizione, nella riga successiva aggiungere il codice seguente:
await args.CompleteMessageAsync(args.Message);
Verificare che il codice finale sia simile all'esempio seguente:
using System; using System.Text; using System.Threading; using System.Threading.Tasks; using Azure.Messaging.ServiceBus; namespace performancemessagereceiver { class Program { const string ServiceBusConnectionString = "Endpoint=sb://alexgeddyneil.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx"; const string TopicName = "salesperformancemessages"; const string SubscriptionName = "Americas"; static void Main(string[] args) { MainAsync().GetAwaiter().GetResult(); } static async Task MainAsync() { var client = new ServiceBusClient(ServiceBusConnectionString); Console.WriteLine("======================================================"); Console.WriteLine("Press ENTER key to exit after receiving all the messages."); Console.WriteLine("======================================================"); var processorOptions = new ServiceBusProcessorOptions { MaxConcurrentCalls = 1, AutoCompleteMessages = false }; ServiceBusProcessor processor = client.CreateProcessor(TopicName, SubscriptionName, processorOptions); processor.ProcessMessageAsync += MessageHandler; processor.ProcessErrorAsync += ErrorHandler; await processor.StartProcessingAsync(); Console.Read(); await processor.DisposeAsync(); await client.DisposeAsync(); } static async Task MessageHandler(ProcessMessageEventArgs args) { Console.WriteLine($"Received message: SequenceNumber:{args.Message.SequenceNumber} Body:{args.Message.Body}"); await args.CompleteMessageAsync(args.Message); } static Task ErrorHandler(ProcessErrorEventArgs args) { Console.WriteLine($"Message handler encountered an exception {args.Exception}."); Console.WriteLine("Exception context for troubleshooting:"); Console.WriteLine($"- Endpoint: {args.FullyQualifiedNamespace}"); Console.WriteLine($"- Entity Path: {args.EntityPath}"); Console.WriteLine($"- Executing Action: {args.ErrorSource}"); return Task.CompletedTask; } } }
Per salvare le modifiche, premere CTRL+S e quindi CTRL+Q per chiudere l'editor.
Recuperare un messaggio dell'argomento da una sottoscrizione
Per eseguire il componente che recupera un messaggio sull'andamento delle vendite da una sottoscrizione, immettere il comando seguente:
dotnet run --project performancemessagereceiver
L'output sarà simile all'esempio seguente:
Received message: SequenceNumber:1 Body:Total sales for Brazil in August: $13m.
Quando il programma ha restituito le notifiche relative alla ricezione dei messaggi, premere INVIO per arrestare l'app.
Controllare il numero dei messaggi dopo aver recuperato un messaggio per una sottoscrizione
Eseguire il comando seguente per confermare che non vi sono messaggi rimanenti nella sottoscrizione Americas
. Assicurarsi di sostituire <namespace-name> con lo spazio dei nomi del bus di servizio.
az servicebus topic subscription show \
--resource-group "<rgn>[sandbox resource group name]</rgn>" \
--topic-name salesperformancemessages \
--name Americas \
--query messageCount \
--namespace-name <namespace-name>
Se si sostituisce Americas
con EuropeAndAsia
in questo codice per visualizzare il numero attuale dei messaggi per la sottoscrizione EuropeAndAsia
, si noterà che il conteggio dei messaggi è 1
. Nel codice precedente, solo Americas
è stato impostato per recuperare i messaggi dell'argomento, in modo che il messaggio sia ancora in attesa di EuropeAndAsia
per recuperarlo.