Självstudie: Uppdatera lagret med Azure-portalen och ämnen/prenumerationer

Azure Service Bus är en meddelandetjänst i molnet för flera klienter som skickar information mellan program och tjänster. Asynkrona åtgärder ger dig en flexibel, asynkron meddelandetjänst med funktioner för strukturerade meddelanden enligt FIFO-metoden (först-in-först-ut) och funktioner för publicering/prenumeration. Detaljerad översikt över Azure Service Bus finns i Vad är Service Bus?.

Den här kursen visar hur du använder Service Bus-ämnen och prenumerationer i ett scenario med butikslager, med publicera/prenumerera kanaler med Azure-portalen och .NET. Ett exempel på det här scenariot är en uppdatering av lagersortimentet för flera butiker. I det här scenariot, får varje butik eller uppsättning butiker meddelanden för att uppdatera sina sortiment. Den här självstudien visar hur du implementerar det här scenariot med prenumerationer och filter. Först skapar du ett ämne med tre prenumerationer, lägger till några regler och filter och skickar och tar sedan emot meddelanden från ämnet och prenumerationerna.

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

I den här självstudien lär du dig att:

  • Skapa ett Service Bus-ämne och tre prenumerationer på det ämnet med hjälp av Azure-portalen
  • Lägga till filter för prenumerationer med hjälp av .NET-kod
  • Skapa meddelanden med olika innehåll
  • Skicka meddelanden och kontrollera att de kom till de förväntade prenumerationerna
  • Ta emot meddelanden från prenumerationerna

Förutsättningar

För att kunna följa den här självstudien måste du ha:

  • Azure-prenumeration. Om du vill använda Azure-tjänster, inklusive Azure Service Bus, behöver du en prenumeration. Om du inte har någon Azure-prenumeration kan du skapa ett kostnadsfritt konto innan du börjar.
  • Visual Studio 2019 eller senare.

Service Bus-ämnen och prenumerationer

Varje prenumeration på ett ämne får en kopia av varje meddelande. Ämnen är fullständigt protokollmässigt och semantiskt kompatibla med Service Bus-köer. Service Bus-ämnen stöder en mängd olika urvalsregler med filtervillkor, med valfria åtgärder som anger eller ändrar meddelandeegenskaperna. Varje gång en regel matchar så genererar den ett meddelande. Mer information om regler, filter och åtgärder, finns på den här länken.

Skapa ett namnområde i Azure Portal

För att komma igång med Service Bus-meddelandeentiteter i Azure måste du först skapa ett namnområde med ett namn som är unikt i Azure. Ett namnområde tillhandahåller en omfångscontainer för Service Bus-resurser (köer, ämnen osv.) i ditt program.

Så här skapar du ett namnområde:

  1. Logga in på Azure-portalen.

  2. Gå till sidan Alla tjänster.

  3. I det vänstra navigeringsfältet väljer du Integrering i listan över kategorier, hovra musen över Service Bus och välj + sedan knappen på Service Bus-panelen.

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

  4. Följ dessa steg i taggen Grundläggande på sidan Skapa namnområde:

    1. För Prenumeration väljer du en Azure-prenumeration där du ska skapa namnrymden.

    2. För Resursgrupp väljer du en befintlig resursgrupp där namnrymden ska finnas, eller så skapar du en ny.

    3. Ange ett namn för namnrymden. Namnområdesnamnet bör följa följande namngivningskonventioner:

      • Namnet måste vara unikt i Hela Azure. Systemet kontrollerar omedelbart om namnet är tillgängligt.
      • Namnlängden är minst 6 och högst 50 tecken.
      • Namnet får endast innehålla bokstäver, siffror, bindestreck "-".
      • Namnet måste börja med en bokstav och sluta med en bokstav eller siffra.
      • Namnet slutar inte med "-sb" eller "-mgmt".
    4. För Plats väljer du land eller region där namnrymden ska finnas.

    5. För Prisnivå väljer du prisnivån (Basic, Standard eller Premium) för namnområdet. För den här snabbstarten väljer du Standard.

      Viktigt!

      Om du vill använda ämnen och prenumerationer väljer du antingen Standard eller Premium. Ämnen/prenumerationer stöds inte på prisnivån Basic.

      Om du har valt prisnivån Premium anger du antalet meddelandeenheter. Premium-nivån ger resursisolering på processor- och minnesnivå så att varje arbetsbelastning körs självständigt. Den här resurscontainern kallas för en meddelandefunktionsenhet. Ett premiumnamnområde har minst en meddelandeenhet. Du kan välja 1, 2, 4, 8 eller 16 meddelandeenheter för varje Service Bus Premium-namnområde. Mer information finns i Service Bus Premium-meddelanden.

    6. Välj Granska + skapa längst ned på sidan.

      Image showing the Create a namespace page

    7. På sidan Granska + skapa granskar du inställningarna och väljer Skapa.

  5. När distributionen av resursen har slutförts väljer du Gå till resurs på distributionssidan.

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

  6. Startsidan för din Service Bus-namnrymd visas.

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

Hämta anslutningssträng till namnområdet (Azure-portalen)

När du skapar ett nytt namnområde genereras automatiskt en inledande SAS-princip (Signatur för delad åtkomst) med primära och sekundära nycklar och primära och sekundära anslutningssträng som var och en ger fullständig kontroll över alla aspekter av namnområdet. Se Service Bus – autentisering och auktorisering för mer information om hur du skapar regler med mer begränsade rättigheter för regelbundna sändare och mottagare.

En klient kan använda anslutningssträng för att ansluta till Service Bus-namnområdet. Så här kopierar du den primära anslutningssträng för ditt namnområde:

  1. På sidan Service Bus-namnområde väljer du Principer för delad åtkomst på den vänstra menyn.

  2. På sidan Principer för delad åtkomst väljer du RootManageSharedAccessKey.

  3. I fönstret Princip: RootManageSharedAccessKey väljer du kopieringsknappen bredvid Primär Anslut ionssträng för att kopiera anslutningssträng till Urklipp för senare användning. Klistra in det här värdet i Anteckningar eller på en tillfällig plats.

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

    Du kan använda den här sidan för att kopiera primärnyckel, sekundär nyckel, primär anslutningssträng och sekundär anslutningssträng.

Skapa ett ämne med Azure Portal

  1. På sidan Service Bus Namespace (Service Bus-namnrymd) väljer du Ämnen på den vänstra menyn.

  2. Välj + Ämne i verktygsfältet.

  3. Ange ett namn för ämnet. Lämna standardvärdena för de andra alternativen.

  4. Välj Skapa.

    Screenshot of the Create topic page.

Skapa prenumerationer på ämnet

  1. Välj det ämne som du skapade i föregående avsnitt.

    Screenshot of the Topics page with your topic selected.

  2. På sidan Service Bus-ämne väljer du Prenumerationer från den vänstra menyn och sedan + Prenumeration i verktygsfältet.

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

  3. Följ dessa steg på sidan Skapa prenumeration :

    1. Ange S1 som namn på prenumerationen.

    2. Välj sedan Skapa för att skapa prenumerationen.

      Screenshot of the Create subscription page.

  4. Upprepa föregående steg två gånger för att skapa prenumerationer med namnet S2 och S3.

Skapa filterregler för prenumerationer

När namnområdet och ämnet/prenumerationerna har etablerats och du har anslutningssträng till namnområdet är du redo att skapa filterregler för prenumerationerna och sedan skicka och ta emot meddelanden. Du kan granska koden i den här GitHub-exempelmappen.

Skicka och ta emot meddelanden

Följ dessa steg för att köra koden:

  1. I en kommandotolk eller PowerShell-prompt, klonar du Service Bus GitHub-lagringsplatsen genom att utfärda följande kommando:

    git clone https://github.com/Azure/azure-service-bus.git
    
  2. Navigera till exempelmappen azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters.

  3. Hämta anslutningssträng som du kopierade till Anteckningar tidigare i den här självstudien. Du behöver också namnet på det ämne som du skapade i föregående avsnitt.

  4. Skriv följande kommando i kommandotolken:

    dotnet build
    
  5. Gå till mappen BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1.

  6. Skriv följande kommando för att köra programmet. Se till att ersätta myConnectionString med värdet som du tidigare fick och myTopicName med namnet på det ämne som du skapade:

    dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
    
  7. Följ instruktionerna i konsolen för att välja filterskapande först. En del av att skapa filter är att ta bort standardfiltren. När du använder PowerShell eller CLI behöver du inte ta bort standardfiltret, men om du gör det i kod måste du ta bort dem. Konsolkommandona 1 och 3 hjälper dig att hantera filter för de prenumerationer som du skapade tidigare:

    • Kör 1: för att ta bort standardfiltren.

    • Kör 2: för att lägga till dina egna filter.

    • Kör 3: Hoppa över det här steget för självstudien. Det här alternativet tar eventuellt bort dina egna filter. Standardfiltren återskapas inte.

      Showing output of 2

  8. Efter att filtret har skapats, kan du skicka meddelanden. Tryck på 4 och notera 10 meddelanden som skickas till ämnet:

    Send output

  9. Tryck på 5 och se de meddelanden som tas emot. Om du inte fick tillbaka 10 meddelanden trycker du på "m" för att visa menyn och trycker sedan på 5 igen.

    Receive output

Rensa resurser

När de inte längre behövs följer du de här stegen för att rensa resurser.

  1. Navigera till ditt namnområde i Azure-portalen.
  2. På sidan Service Bus-namnområde väljer du Ta bort från kommandofältet för att ta bort namnområdet och resurserna (köer, ämnen och prenumerationer) i det.

Förstå exempelkoden

Det här avsnittet innehåller mer information om vad exempelkoden gör.

Hämta anslutningssträngen och ämnet

Koden deklarerar först en uppsättning variabler som driver den återstående körningen av programmet.

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.

Anslutningssträngen och ämnets namn skickas in via kommandoradsparametrar som det visas och därefter läses de i Main()-metoden:

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();
    }
}

Ta bort standardfiltren

När du skapar en prenumeration, skapar Service Bus ett standardfilter per prenumeration. Det här filtret låter dig ta emot alla meddelanden som skickas till ämnet. Om du vill använda anpassade filter kan du ta bort standardfiltret som visas i följande kod:

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();
}

Skapa filter

Följande kod lägger till anpassade filter som definierats i den självstudien:

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();
}

Ta bort dina anpassade skapade filter

Om du vill ta bort alla filter för din prenumeration, visar följande kod hur du gör detta:

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();
}

Skicka meddelanden

Att skicka meddelanden till ett ämne liknar att skicka meddelanden till en kö. Det här exemplet visar hur du skickar meddelanden med hjälp av en uppgiftslista och asynkron bearbetning:

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()}"); ;
    }
}

Ta emot meddelanden

Meddelanden tas emot igen via en uppgiftslista och koden använder batchbearbetning. Du kan skicka och ta emot med batchbearbetning, men det här exemplet visar bara hur du tar emot i batch. I verkligheten skulle du inte bryta dig ur loopen, utan fortsätta loopa och ange ett högre tidsintervall, till exempel en minut. Det mottagna samtalet till koordinatorn hålls öppet under den här tiden och om meddelandena tas emot returneras de omedelbart och ett nytt mottagningssamtal utfärdas. Det här konceptet kallas lång avsökning. Att använda mottagningspumpen, som du kan se i snabbstarten och i flera andra exempel på lagringsplatsen, är ett mer typiskt alternativ.

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());
        }
    }
}

Kommentar

Du kan hantera Service Bus-resurser med Service Bus Explorer. Med Service Bus Explorer kan användare ansluta till ett Service Bus-namnområde och administrera meddelandeentiteter på ett enkelt sätt. Verktyget innehåller avancerade funktioner som import-/exportfunktioner eller möjligheten att testa ämne, köer, prenumerationer, relätjänster, meddelandehubbar och händelsehubbar.

Nästa steg

I den här självstudien, etablerade du resurser med hjälp av Azure-portalen och därefter skickade du och tog emot meddelanden från ett Service Bus-ämne och dess prenumerationer. Du har lärt dig att:

  • Skapa ett Service Bus-ämne och en eller flera prenumerationer på det ämnet med Azure-portalen
  • Lägg till ämnesfilter med .NET-kod
  • Skapa två meddelanden med olika innehåll
  • Skicka meddelandena och verifiera att de anlände i de förväntade prenumerationerna
  • Ta emot meddelanden från prenumerationerna

Om du vill ha fler exempel på att skicka och ta emot meddelanden, kan du komma igång med Service Bus-exempel på GitHub.

Gå vidare till nästa självstudie för att läsa mer om att använda Service Bus-funktionerna publicera/prenumerera.