Esercitazione: Aggiornare l'inventario usando il portale di Azure e argomenti/sottoscrizioni

Il bus di servizio di Azure è un servizio di messaggistica multi-tenant che invia informazioni tra applicazioni e servizi. Le operazioni asincrone offrono messaggistica negoziata flessibile, insieme a funzionalità di messaggistica e pubblicazione/sottoscrizione FIFO (First-In-First-Out) strutturate. Per una panoramica dettagliata del Bus di servizio di Azure, vedere Informazioni sul Bus di servizio.

Questa esercitazione illustra come usare gli argomenti del bus di servizio e le sottoscrizioni in uno scenario di magazzino al dettaglio, con i canali di pubblicazione/sottoscrizione tramite il portale di Azure e .NET. Un esempio di questo scenario è un aggiornamento dell'assortimento di magazzino per più punti vendita al dettaglio. In questo scenario ogni negozio o set di negozi ottiene i messaggi a essi destinati per aggiornare gli assortimenti. Questa esercitazione illustra come implementare lo scenario usando filtri e sottoscrizioni. Si crea prima di tutto un argomento con tre sottoscrizioni, si aggiungono alcune regole e filtri quindi si inviano e ricevono messaggi dall'argomento e dalle sottoscrizioni.

Immagine che mostra un mittente, un argomento con tre sottoscrizioni e tre ricevitori.

In questa esercitazione apprenderai a:

  • Creare un argomento del Bus di servizio e tre sottoscrizioni a tale argomento usando il portale di Azure
  • Aggiungere filtri per le sottoscrizioni usando il codice .NET
  • Creare messaggi con contenuto differente
  • Inviare i messaggi e verificare che siano arrivati nelle sottoscrizioni previste
  • Ricevere messaggi dalle sottoscrizioni

Prerequisiti

Per completare questa esercitazione, accertarsi di avere:

  • Sottoscrizione di Azure. Per usare i servizi di Azure, tra cui Bus di servizio di Azure, è necessaria una sottoscrizione. Se non si ha una sottoscrizione di Azure, è possibile creare un account gratuito prima di iniziare.
  • Visual Studio 2019 o versione successiva.

Argomenti e sottoscrizioni del bus di servizio

Ogni sottoscrizione a un argomento può ricevere una copia di ogni messaggio. Gli argomenti sono completamente compatibili a livello di protocollo e di semantica con le code del bus di servizio. Gli argomenti del bus di servizio supportano un'ampia gamma di regole di selezione con condizioni di filtro, con azioni facoltative per impostare o modificare le proprietà dei messaggi. Ogni volta che una regola corrisponde, genera un messaggio. Per altre informazioni su regole, filtri e azioni, seguire questo collegamento.

Creare uno spazio dei nomi nel portale di Azure

Per iniziare a usare le entità di messaggistica del bus di servizio in Azure, prima di tutto è necessario creare uno spazio dei nomi con un nome univoco in Azure. Uno spazio dei nomi fornisce un contenitore di ambito per le risorse del Bus di servizio (code, argomenti, ecc.) all'interno dell'applicazione.

Per creare uno spazio dei nomi:

  1. Accedere al portale di Azure.

  2. Andare alla pagina Tutti i servizi.

  3. Nella barra di spostamento a sinistra selezionare Integrazione nell'elenco delle categorie, passare il puntatore del mouse sul Bus di servizio quindi selezionare il pulsante + nel riquadro Bus di servizio.

    Immagine che mostra la selezione di Crea una risorsa, Integrazione quindi Bus di servizio nel menu.

  4. Nel tag Dati principali della pagina Crea spazio dei nomi seguire questa procedura:

    1. Per Sottoscrizione scegliere una sottoscrizione di Azure in cui creare lo spazio dei nomi.

    2. Per Gruppo di risorse scegliere un gruppo di risorse esistente in cui risiederà lo spazio dei nomi oppure crearne uno nuovo.

    3. Immettere un nome per lo spazio dei nomi. Il nome dello spazio dei nomi deve rispettare le seguenti convenzioni di denominazione:

      • Il nome deve essere univoco in Azure. Verrà effettuato immediatamente un controllo sulla disponibilità del nome.
      • La lunghezza del nome deve essere compresa tra 6 e 50 caratteri.
      • Il nome può contenere solo lettere, numeri e trattini "-".
      • Il nome deve iniziare con una lettera e terminare con una lettera o un numero.
      • Il nome non termina con "-sb" o "-mgmt".
    4. Per Localitàscegliere l'area in cui deve essere ospitato lo spazio dei nomi.

    5. In Piano tariffario, selezionare il piano tariffario (Basic, Standard o Premium) per lo spazio dei nomi. Per questo avvio rapido selezionare Standard.

      Importante

      Se si vogliono usare argomenti e sottoscrizioni, scegliere Standard o Premium. Argomenti e sottoscrizioni non sono supportati nel piano tariffario Basic.

      Se è stato selezionato il piano tariffario Premium, specificare il numero di unità di messaggistica. Il piano Premium fornisce l'isolamento delle risorse a livello di CPU e memoria in modo che ogni carico di lavoro venga eseguito in isolamento. Questo contenitore di risorse viene chiamato unità di messaggistica. Uno spazio dei nomi Premium ha almeno un'unità di messaggistica. È possibile acquistare 1, 2, 4, 8 o 16 unità di messaggistica per ogni spazio dei nomi Premium del Bus di servizio. Per altre informazioni, vedere Messaggistica Premium del bus di servizio.

    6. Selezionare Rivedi e crea nella parte inferiore della pagina.

      Immagine che mostra la pagina Creare uno spazio dei nomi

    7. Nella pagina Rivedi + crea controllare le impostazioni e selezionare Crea.

  5. Al termine della distribuzione della risorsa, selezionare Vai alla risorsa nella pagina di distribuzione.

    Immagine che mostra la pagina distribuzione riuscita con il link Vai alla risorsa.

  6. Viene visualizzata la home page dello spazio dei nomi del bus di servizio.

    Immagine che mostra la home page dello spazio dei nomi del Bus di servizio creato.

Ottenere la stringa di connessione allo spazio dei nomi (portale di Azure)

Con la creazione di un nuovo spazio dei nomi viene generato automaticamente un criterio di Firma di accesso condiviso (SAS) con chiavi primaria e secondaria e stringhe di connessione primaria e secondaria, ognuna delle quali concede il controllo completo su tutti gli aspetti dello spazio dei nomi. Per informazioni su come creare regole con diritti più limitati per mittenti e ricevitori, vedere Autenticazione e autorizzazione del bus di servizio.

Un client può usare la stringa di connessione per connettersi allo spazio dei nomi di Bus di servizio. Per copiare la stringa di connessione primaria per lo spazio dei nomi, procedere come segue:

  1. Nella pagina Spazio dei nomi di Bus di servizio selezionare Criteri di accesso condivisi nel menu a sinistra.

  2. Nella pagina Criteri di accesso condiviso selezionare RootManageSharedAccessKey.

  3. Nella finestra Criteri: RootManageSharedAccessKey selezionare il pulsante Copia accanto a Stringa di connessione primaria per copiare la stringa di connessione negli Appunti e usarla in un secondo momento. Incollare questo valore nel Blocco note o in un'altra posizione temporanea.

    Screenshot che mostra un criterio di firma di accesso condiviso denominato RootManageSharedAccessKey, che include chiavi e stringhe di connessione.

    È possibile usare questa pagina per copiare la chiave primaria, la chiave secondaria, la stringa di connessione primaria e la stringa di connessione secondaria.

Creare un argomento usando il portale di Azure

  1. Nella pagina Spazio dei nomi del bus di servizio scegliere Argomenti dal menu a sinistra.

  2. Selezionare + Argomento sulla barra degli strumenti.

  3. Immettere un nome per l'argomento. Lasciare invariati i valori predefiniti delle altre opzioni.

  4. Seleziona Crea.

    Screenshot della pagina Crea argomento.

Creare le sottoscrizioni dell'argomento

  1. Selezionare l'argomento creato nella sezione precedente.

    Screenshot della pagina Argomenti con l'argomento selezionato.

  2. Nella pagina Argomento del bus di servizio scegliere Sottoscrizioni dal menu a sinistra e quindi selezionare + Sottoscrizione sulla barra degli strumenti.

    Screenshot della pagina Sottoscrizioni con il pulsante Aggiungi sottoscrizione selezionato.

  3. Nella pagina Crea sottoscrizione procedere come segue:

    1. Immettere S1 per il nome della sottoscrizione.

    2. Successivamente, selezionare Crea per creare la sottoscrizione.

      Screenshot della pagina Crea sottoscrizione.

  4. Ripetere due volte il passaggio precedente per creare le sottoscrizioni denominate S2 ed S3.

Creare regole di filtro nelle sottoscrizioni

Dopo che è stato effettuato il provisioning dello spazio dei nomi e di argomento/sottoscrizioni ed è disponibile la stringa di connessione allo spazio dei nomi, è possibile creare regole di filtro nelle sottoscrizioni, quindi inviare e ricevere messaggi. È possibile esaminare il codice in questa cartella dell'esempio di GitHub.

Inviare e ricevere messaggi

Per eseguire il codice, seguire questa procedura:

  1. In un prompt dei comandi o di PowerShell clonare il repository GitHub del bus di servizio eseguendo il comando seguente:

    git clone https://github.com/Azure/azure-service-bus.git
    
  2. Passare alla cartella dell'esempio azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters.

  3. Ottenere la stringa di connessione copiata in Blocco note in precedenza in questa esercitazione. È anche necessario il nome dell'argomento creato nella sezione precedente.

  4. Al prompt dei comandi digitare quanto segue:

    dotnet build
    
  5. Passa alla cartella BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1.

  6. Digitare il comando seguente per eseguire il programma. Assicurarsi di sostituire myConnectionString con il valore ottenuto in precedenza e myTopicName con il nome dell'argomento creato:

    dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
    
  7. Seguire le istruzioni nella console per selezionare prima la creazione dei filtri. Parte della creazione di filtri consiste nel rimuovere i filtri predefiniti. Quando si usa PowerShell o l'interfaccia della riga di comando, non è necessario rimuovere i filtri predefiniti, ma, se si esegue questa operazione nel codice, è necessario rimuoverli. I comandi della console 1 e 3 consentono di gestire i filtri nelle sottoscrizioni create in precedenza:

    • Esecuzione 1: per rimuovere i filtri predefiniti.

    • Esecuzione 2: per aggiungere filtri personalizzati.

    • Eseguire 3: Ignorare questo passaggio per l'esercitazione. Questa opzione rimuove facoltativamente i propri filtri. Non ricrea i filtri predefiniti.

      Output di 2

  8. Dopo la creazione del filtro, è possibile inviare messaggi. Premere 4 e osservare l'invio di 10 messaggi all'argomento:

    Inviare l'output

  9. Premere 5 e osservare la ricezione dei messaggi. Se non si ottengono nuovamente 10 messaggi, premere "m" per visualizzare il menu, quindi premere ancora 5.

    Output di ricezione

Pulire le risorse

Seguire questa procedura per pulire le risorse non più necessarie.

  1. Passare allo spazio dei nomi nel portale di Azure.
  2. Nella pagina Spazio dei nomi del Bus di servizio selezionare Elimina dalla barra dei comandi per eliminare lo spazio dei nomi e le risorse (code, argomenti e sottoscrizioni).

Informazioni sul codice di esempio

Questa sezione contiene altri dettagli sulle operazioni eseguite dal codice di esempio.

Ottenere la stringa di connessione e l'argomento

Il codice dichiara prima di tutto un set di variabili, che determinano l'esecuzione rimanente del programma.

string ServiceBusConnectionString;
string TopicName;

static string[] Subscriptions = { "S1", "S2", "S3" };
static IDictionary<string, string[]> SubscriptionFilters = new Dictionary<string, string[]> {
    { "S1", new[] { "StoreId IN('Store1', 'Store2', 'Store3')", "StoreId = 'Store4'"} },
    { "S2", new[] { "sys.To IN ('Store5','Store6','Store7') OR StoreId = 'Store8'" } },
    { "S3", new[] { "sys.To NOT IN ('Store1','Store2','Store3','Store4','Store5','Store6','Store7','Store8') OR StoreId NOT IN ('Store1','Store2','Store3','Store4','Store5','Store6','Store7','Store8')" } }
};
// You can have only have one action per rule and this sample code supports only one action for the first filter, which is used to create the first rule. 
static IDictionary<string, string> SubscriptionAction = new Dictionary<string, string> {
    { "S1", "" },
    { "S2", "" },
    { "S3", "SET sys.Label = 'SalesEvent'"  }
};
static string[] Store = { "Store1", "Store2", "Store3", "Store4", "Store5", "Store6", "Store7", "Store8", "Store9", "Store10" };
static string SysField = "sys.To";
static string CustomField = "StoreId";
static int NrOfMessagesPerStore = 1; // Send at least 1.

La stringa di connessione e il nome dell'argomento vengono passati tramite i parametri della riga di comando come illustrato e quindi vengono letti nel metodo Main():

static void Main(string[] args)
{
    string ServiceBusConnectionString = "";
    string TopicName = "";

    for (int i = 0; i < args.Length; i++)
    {
        if (args[i] == "-ConnectionString")
        {
            Console.WriteLine($"ConnectionString: {args[i + 1]}");
            ServiceBusConnectionString = args[i + 1]; // Alternatively enter your connection string here.
        }
        else if (args[i] == "-TopicName")
        {
            Console.WriteLine($"TopicName: {args[i + 1]}");
            TopicName = args[i + 1]; // Alternatively enter your queue name here.
        }
    }

    if (ServiceBusConnectionString != "" && TopicName != "")
    {
        Program P = StartProgram(ServiceBusConnectionString, TopicName);
        P.PresentMenu().GetAwaiter().GetResult();
    }
    else
    {
        Console.WriteLine("Specify -Connectionstring and -TopicName to execute the example.");
        Console.ReadKey();
    }
}

Rimuovere i filtri predefiniti

Quando si crea una sottoscrizione, il bus di servizio crea un filtro predefinito per ogni sottoscrizione. Questo filtro consente di ricevere ogni messaggio inviato all'argomento. Per usare i filtri personalizzati, è possibile rimuovere il filtro predefinito, come illustrato nel codice seguente:

private async Task RemoveDefaultFilters()
{
    Console.WriteLine($"Starting to remove default filters.");

    try
    {
        var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
        foreach (var subscription in Subscriptions)
        {
            await client.DeleteRuleAsync(TopicName, subscription, CreateRuleOptions.DefaultRuleName);
            Console.WriteLine($"Default filter for {subscription} has been removed.");
        }

        Console.WriteLine("All default Rules have been removed.\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    await PresentMenu();
}

Creare filtri

Il codice seguente aggiunge i filtri personalizzati definiti in questa esercitazione:

private async Task CreateCustomFilters()
{
    try
    {
        for (int i = 0; i < Subscriptions.Length; i++)
        {
            var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
            string[] filters = SubscriptionFilters[Subscriptions[i]];
            if (filters[0] != "")
            {
                int count = 0;
                foreach (var myFilter in filters)
                {
                    count++;

                    string action = SubscriptionAction[Subscriptions[i]];
                    if (action != "")
                    {
                        await client.CreateRuleAsync(TopicName, Subscriptions[i], new CreateRuleOptions
                        {
                            Filter = new SqlRuleFilter(myFilter),
                            Action = new SqlRuleAction(action),
                            Name = $"MyRule{count}"
                        });
                    }
                    else
                    {
                        await client.CreateRuleAsync(TopicName, Subscriptions[i], new CreateRuleOptions
                        {
                            Filter = new SqlRuleFilter(myFilter),
                            Name = $"MyRule{count}"
                        });
                    }
                }
            }

            Console.WriteLine($"Filters and actions for {Subscriptions[i]} have been created.");
        }

        Console.WriteLine("All filters and actions have been created.\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    await PresentMenu();
}

Rimuovere i filtri personalizzati creati

Se si vogliono rimuovere tutti i filtri nella sottoscrizione, il codice seguente illustra come eseguire questa operazione:

private async Task CleanUpCustomFilters()
{
    foreach (var subscription in Subscriptions)
    {
        try
        {
            var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
            IAsyncEnumerator<RuleProperties> rules = client.GetRulesAsync(TopicName, subscription).GetAsyncEnumerator();
            while (await rules.MoveNextAsync())
            {
                await client.DeleteRuleAsync(TopicName, subscription, rules.Current.Name);
                Console.WriteLine($"Rule {rules.Current.Name} has been removed.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
    Console.WriteLine("All default filters have been removed.\n");

    await PresentMenu();
}

Inviare messaggi

L'invio di messaggi a un argomento è simile all'invio di messaggi a una coda. Questo esempio mostra come inviare messaggi, usando un elenco di attività e l'elaborazione asincrona:

public async Task SendMessages()
{
    try
    {
        await using var client = new ServiceBusClient(ServiceBusConnectionString);
        var taskList = new List<Task>();
        for (int i = 0; i < Store.Length; i++)
        {
            taskList.Add(SendItems(client, Store[i]));
        }

        await Task.WhenAll(taskList);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    Console.WriteLine("\nAll messages sent.\n");
}

private async Task SendItems(ServiceBusClient client, string store)
{
    // create the sender
    ServiceBusSender tc = client.CreateSender(TopicName);

    for (int i = 0; i < NrOfMessagesPerStore; i++)
    {
        Random r = new Random();
        Item item = new Item(r.Next(5), r.Next(5), r.Next(5));

        // Note the extension class which is serializing an deserializing messages
        ServiceBusMessage message = item.AsMessage();
        message.To = store;
        message.ApplicationProperties.Add("StoreId", store);
        message.ApplicationProperties.Add("Price", item.GetPrice().ToString());
        message.ApplicationProperties.Add("Color", item.GetColor());
        message.ApplicationProperties.Add("Category", item.GetItemCategory());

        await tc.SendMessageAsync(message);
        Console.WriteLine($"Sent item to Store {store}. Price={item.GetPrice()}, Color={item.GetColor()}, Category={item.GetItemCategory()}"); ;
    }
}

Ricevere messaggi

I messaggi vengono ricevuti nuovamente tramite un elenco di attività e il codice usa l'invio in batch. È possibile inviare e ricevere messaggi usando l'invio in batch, ma questo esempio mostra solo la ricezione in batch. Anche se di fatto il ciclo non verrà interrotto, continuare a eseguirlo e impostare un intervallo di tempo superiore, ad esempio un minuto. La chiamata di ricezione al broker viene lasciata aperta per questo periodo di tempo e, se arrivano messaggi, vengono immediatamente restituiti e viene effettuata una nuova chiamata di ricezione. Questo concetto è denominato polling di lunga durata. L'uso della distribuzione della ricezione che è possibile visualizzare nell'avvio rapido e in diversi altri esempi del repository, è un'opzione più comune.

public async Task Receive()
{
    var taskList = new List<Task>();
    for (var i = 0; i < Subscriptions.Length; i++)
    {
        taskList.Add(this.ReceiveMessages(Subscriptions[i]));
    }

    await Task.WhenAll(taskList);
}

private async Task ReceiveMessages(string subscription)
{
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    ServiceBusReceiver receiver = client.CreateReceiver(TopicName, subscription);

    // In reality you would not break out of the loop like in this example but would keep looping. The receiver keeps the connection open
    // to the broker for the specified amount of seconds and the broker returns messages as soon as they arrive. The client then initiates
    // a new connection. So in reality you would not want to break out of the loop. 
    // Also note that the code shows how to batch receive, which you would do for performance reasons. For convenience you can also always
    // use the regular receive pump which we show in our Quick Start and in other GitHub samples.
    while (true)
    {
        try
        {
            //IList<Message> messages = await receiver.ReceiveAsync(10, TimeSpan.FromSeconds(2));
            // Note the extension class which is serializing an deserializing messages and testing messages is null or 0.
            // If you think you did not receive all messages, just press M and receive again via the menu.
            IReadOnlyList<ServiceBusReceivedMessage> messages = await receiver.ReceiveMessagesAsync(maxMessages: 100);

            if (messages.Any())
            {
                foreach (ServiceBusReceivedMessage message in messages)
                {
                    lock (Console.Out)
                    {
                        Item item = message.As<Item>();
                        IReadOnlyDictionary<string, object> myApplicationProperties = message.ApplicationProperties;
                        Console.WriteLine($"StoreId={myApplicationProperties["StoreId"]}");
                        if (message.Subject != null)
                        {
                            Console.WriteLine($"Subject={message.Subject}");
                        }
                        Console.WriteLine(
                            $"Item data: Price={item.GetPrice()}, Color={item.GetColor()}, Category={item.GetItemCategory()}");
                    }

                    await receiver.CompleteMessageAsync(message);
                }
            }
            else
            {
                break;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

Nota

È possibile gestire le risorse del bus di servizio con Service Bus Explorer. Service Bus Explorer consente agli utenti di connettersi a uno spazio dei nomi del bus di servizio e di amministrare le entità di messaggistica in modo semplice. Lo strumento offre caratteristiche avanzate, tra cui funzionalità di importazione/esportazione o la possibilità di testare argomenti, code, sottoscrizioni, servizi di inoltro, hub di notifica e hub eventi.

Passaggi successivi

In questa esercitazione è stato effettuato il provisioning delle risorse usando il portale di Azure, quindi sono stati inviati e ricevuti messaggi da un argomento del bus di servizio e dalle relative sottoscrizioni. Contenuto del modulo:

  • Creare un argomento del bus di servizio e una o più sottoscrizioni a tale argomento usando il portale di Azure
  • Aggiungere filtri di argomento usando il codice .NET
  • Creare due messaggi con contenuto differente
  • Inviare i messaggi e verificare che siano arrivati nelle sottoscrizioni previste
  • Ricevere messaggi dalle sottoscrizioni

Per altri esempi di invio e ricezione dei messaggi, vedere gli esempi del bus di servizio su GitHub.

Passare alla prossima esercitazione per altre informazioni su come usare le funzionalità di pubblicazione/sottoscrizione del bus di servizio.