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 delle bus di servizio di Azure, vedere Che cos'è 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. Prima di tutto, si crea un argomento con tre sottoscrizioni, si aggiungono alcune regole e filtri e quindi si inviano e si ricevono messaggi dall'argomento e dalle sottoscrizioni.

Image showing a sender, a topic with three subscriptions, and three receivers.

In questa esercitazione apprenderai a:

  • Creare un argomento 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 diverso
  • Inviare 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 bus di servizio risorse (code, argomenti e così via) all'interno dell'applicazione.

Per creare uno spazio dei nomi:

  1. Accedere al portale di Azure.

  2. Passare alla pagina Tutti i servizi.

  3. Sulla barra di spostamento a sinistra selezionare Integrazione nell'elenco delle categorie, passare il puntatore del mouse su bus di servizio e quindi selezionare + il pulsante nel riquadro bus di servizio.

    Image showing selection of Create a resource, Integration, and then Service Bus in the menu.

  4. Nel tag Informazioni di base 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 convenzioni di denominazione seguenti:

      • Il nome deve essere univoco in Azure. Verrà effettuato immediatamente un controllo sulla disponibilità del nome.
      • La lunghezza del nome è almeno 6 e al massimo 50 caratteri.
      • Il nome può contenere solo lettere, numeri, 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. Per Piano tariffario selezionare il piano tariffario (Basic, Standard o Premium) per lo spazio dei nomi. Per questa guida introduttiva selezionare Standard.

      Importante

      Se si vogliono usare argomenti e sottoscrizioni, scegliere Standard o Premium. Gli argomenti e le 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 selezionare 1, 2, 4, 8 o 16 unità di messaggistica per ogni spazio dei nomi bus di servizio Premium. Per altre informazioni, vedere Messaggistica Premium del bus di servizio.

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

      Image showing the Create a namespace page

    7. Nella pagina Rivedi e crea rivedere le impostazioni e selezionare Crea.

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

    Image showing the deployment succeeded page with the Go to resource link.

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

    Image showing the home page of the Service Bus namespace created.

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

La creazione di un nuovo spazio dei nomi genera automaticamente un criterio di firma di accesso condiviso iniziale con chiavi primarie e secondarie e stringa di connessione primarie e secondarie che concedono 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 il stringa di connessione per connettersi allo spazio dei nomi bus di servizio. Per copiare il stringa di connessione primario per lo spazio dei nomi, seguire questa procedura:

  1. Nella pagina spazio dei nomi bus di servizio selezionare Criteri di accesso condiviso 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 il stringa di connessione negli Appunti per usarlo in un secondo momento. Incollare questo valore nel Blocco note o in un'altra posizione temporanea.

    Screenshot shows an S A S policy called RootManageSharedAccessKey, which includes keys and connection strings.

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

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 of the Create topic page.

Creare le sottoscrizioni dell'argomento

  1. Selezionare l'argomento creato nella sezione precedente.

    Screenshot of the Topics page with your topic selected.

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

    Screenshot of the Subscriptions page with the Add subscription button selected.

  3. Nella pagina Crea sottoscrizione seguire questa procedura:

    1. Immettere S1 per nome della sottoscrizione.

    2. Selezionare quindi Crea per creare la sottoscrizione.

      Screenshot of the Create subscription page.

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

Creare regole di filtro nelle sottoscrizioni

Dopo aver effettuato il provisioning dello spazio dei nomi e degli argomenti/sottoscrizioni e aver eseguito il stringa di connessione allo spazio dei nomi, è possibile creare regole di filtro per le 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 il stringa di connessione copiato 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 il filtro predefinito, ma se lo si esegue 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.

      Showing output of 2

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

    Send output

  9. Premere 5 e osservare la ricezione dei messaggi. Se non hai restituito 10 messaggi, premi "m" per visualizzare il menu, quindi premi di nuovo 5.

    Receive output

Pulire le risorse

Quando non sono più necessari, seguire questa procedura per pulire le risorse.

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

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. In realtà, non si interrompe il ciclo, ma si mantiene il ciclo e si imposta un intervallo di tempo superiore, ad esempio un minuto. La chiamata di ricezione al broker viene mantenuta aperta per questo periodo di tempo e, se arrivano i messaggi, vengono restituiti immediatamente e viene emessa una nuova chiamata di ricezione. Questo concetto è denominato polling di lunga durata. L'uso della pompa di ricezione, che è possibile visualizzare nella guida introduttiva e in diversi altri esempi nel repository, è un'opzione più tipica.

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.