Samouczek: aktualizowanie magazynu przy użyciu witryny Azure Portal oraz tematów/subskrypcji

Usługa Azure Service Bus to wielodostępna usługa przesyłania komunikatów w chmurze, która przesyła informacje między aplikacjami i usługami. Operacje asynchroniczne umożliwiają elastyczne przesyłanie komunikatów obsługiwanych przez brokera oraz ustrukturyzowane przesyłanie komunikatów typu „pierwszy na wejściu — pierwszy na wyjściu” (FIFO, first-in, first-out) i zapewniają możliwości publikowania/subskrybowania. Aby uzyskać szczegółowe omówienie usługi Azure Service Bus, zobacz Co to jest usługa Service Bus?.

W tym samouczku przedstawiono, jak używać tematów i subskrypcji usługi Service Bus w scenariuszu obejmującym magazyn sklepu sieciowego, gdy kanały publikowania/subskrypcji korzystają z witryny Azure Portal oraz programu .NET. Przykładem tego scenariusza jest aktualizacja asortymentu magazynu na potrzeby wielu sklepów detalicznych. W tym scenariuszu każdy sklep, lub grupa sklepów, otrzymuje komunikaty o potrzebie aktualizacji swojego asortymentu. W tym samouczku przedstawiono, jak wdrożyć ten scenariusz przy użyciu subskrypcji i filtrów. Najpierw należy utworzyć temat z trzema subskrypcjami, dodać reguły i filtry, a następnie wysyłać i odbierać komunikaty z tematu i subskrypcji.

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

Z tego samouczka dowiesz się, jak wykonywać następujące czynności:

  • Tworzenie tematu usługi Service Bus i trzech subskrypcji w tym temacie przy użyciu witryny Azure Portal
  • Dodawanie filtrów dla subskrypcji przy użyciu kodu platformy .NET
  • Tworzenie komunikatów z inną zawartością
  • Wysyłanie komunikatów i sprawdzanie, czy dotarły do oczekiwanych subskrypcji
  • Odbieranie komunikatów z subskrypcji

Wymagania wstępne

Aby ukończyć kroki tego samouczka, upewnij się, że dysponujesz następującymi elementami:

  • Subskrypcja platformy Azure. Do korzystania z usług platformy Azure, w tym usługi Azure Service Bus, potrzebna jest subskrypcja. Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem możesz utworzyć bezpłatne konto.
  • Program Visual Studio 2019 lub nowszy.

Tematy i subskrypcje usługi Service Bus

Każda subskrypcja tematu może otrzymywać kopie wszystkich komunikatów. Tematy są w pełni protokołowane i semantycznie zgodne z kolejkami usługi Service Bus. Tematy usługi Service Bus obsługują najróżniejsze reguły wyboru z warunkami filtru, z użyciem opcjonalnych akcji, które ustawiają lub modyfikują właściwości komunikatów. Za każdym razem, gdy reguła pasuje, generuje komunikat. Aby dowiedzieć się więcej o regułach, filtrach i akcjach, kliknij ten link.

Tworzenie przestrzeni nazw w witrynie Azure Portal

Aby rozpocząć korzystanie z obsługi wiadomości usługi Service Bus na platformie Azure, musisz najpierw utworzyć przestrzeń nazw o nazwie, która jest unikatowa w obrębie platformy Azure. Przestrzeń nazw udostępnia kontener określania zakresu dla zasobów usługi Service Bus (kolejek, tematów itp.) w aplikacji.

Aby utworzyć przestrzeń nazw:

  1. Zaloguj się w witrynie Azure Portal.

  2. Przejdź do strony Wszystkie usługi.

  3. Na lewym pasku nawigacyjnym wybierz pozycję Integracja z listy kategorii, umieść wskaźnik myszy na usłudze Service Bus, a następnie wybierz + przycisk na kafelku usługi Service Bus.

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

  4. W tagu Podstawowe na stronie Tworzenie przestrzeni nazw wykonaj następujące kroki:

    1. W polu Subskrypcja wybierz subskrypcję platformy Azure, w której ma zostać utworzona przestrzeń nazw.

    2. W polu Grupa zasobów wybierz istniejącą grupę zasobów, w której znajdzie się przestrzeń nazw, lub utwórz nową.

    3. Wprowadź nazwę przestrzeni nazw. Nazwa przestrzeni nazw powinna być zgodna z następującymi konwencjami nazewnictwa:

      • Nazwa musi być unikatowa na platformie Azure. System od razu sprawdza, czy nazwa jest dostępna.
      • Długość nazwy wynosi co najmniej 6 i co najwyżej 50 znaków.
      • Nazwa może zawierać tylko litery, cyfry, łączniki "-".
      • Nazwa musi zaczynać się literą i kończyć literą lub cyfrą.
      • Nazwa nie kończy się ciągiem "-sb" ani "-mgmt".
    4. W polu Lokalizacja wybierz region, w którym powinna być hostowana przestrzeń nazw.

    5. W obszarze Warstwa cenowa wybierz warstwę cenową (Podstawowa, Standardowa lub Premium) dla przestrzeni nazw. W tym przewodniku Szybki start wybierz pozycję Standardowa.

      Ważne

      Jeśli chcesz korzystać z tematów i subskrypcji, wybierz warstwę Standardowa lub Premium. Tematy/subskrypcje nie są obsługiwane w warstwie cenowej Podstawowa.

      W przypadku wybrania warstwy cenowej Premium określ liczbę jednostek obsługi komunikatów. Warstwa Premium zapewnia izolację zasobów na poziomie procesora i pamięci, dlatego poszczególne obciążenia są od siebie odizolowane. Ten kontener zasobów jest nazywany jednostką obsługi komunikatów. Przestrzeń nazw w warstwie Premium ma co najmniej jedną jednostkę obsługi komunikatów. Możesz wybrać 1, 2, 4, 8 lub 16 jednostek obsługi komunikatów dla każdej przestrzeni nazw usługi Service Bus Premium. Aby uzyskać więcej informacji, zobacz Obsługa komunikatów w usłudze Service Bus w warstwie Premium.

    6. Wybierz pozycję Przejrzyj i utwórz w dolnej części strony.

      Image showing the Create a namespace page

    7. Na stronie Przeglądanie + tworzenie przejrzyj ustawienia i wybierz pozycję Utwórz.

  5. Po pomyślnym wdrożeniu zasobu wybierz pozycję Przejdź do zasobu na stronie wdrożenia.

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

  6. Zostanie wyświetlona strona główna dla przestrzeni nazw usługi Service Bus.

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

Uzyskiwanie parametry połączenia do przestrzeni nazw (witryna Azure Portal)

Utworzenie nowej przestrzeni nazw automatycznie generuje początkowe zasady sygnatury dostępu współdzielonego (SAS) z kluczami podstawowymi i pomocniczymi oraz podstawowymi i pomocniczymi parametry połączenia, które zapewniają pełną kontrolę nad wszystkimi aspektami przestrzeni nazw. Zapoznaj się z artykułem Uwierzytelnianie i autoryzacja w usłudze Service Bus, aby dowiedzieć się, jak utworzyć reguły z bardziej ograniczonymi prawami dla zwykłych nadawców i odbiorców.

Klient może użyć parametry połączenia do nawiązania połączenia z przestrzenią nazw usługi Service Bus. Aby skopiować parametry połączenia podstawową dla przestrzeni nazw, wykonaj następujące kroki:

  1. Na stronie Przestrzeń nazw usługi Service Bus wybierz pozycję Zasady dostępu współdzielonego w menu po lewej stronie.

  2. Na stronie Zasady dostępu współdzielonego wybierz pozycję RootManageSharedAccessKey.

  3. W oknie Zasady: RootManageSharedAccessKey wybierz przycisk kopiowania obok pozycji Podstawowy ciąg Połączenie ion, aby skopiować parametry połączenia do schowka do późniejszego użycia. Wklej tę wartość do Notatnika lub innej tymczasowej lokalizacji.

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

    Ta strona służy do kopiowania klucza podstawowego, klucza pomocniczego, parametry połączenia podstawowego i pomocniczego parametry połączenia.

Tworzenie tematu przy użyciu witryny Azure Portal

  1. Na stronie Przestrzeń nazw usługi Service Bus wybierz pozycję Tematy z menu po lewej stronie.

  2. Wybierz pozycję + Temat na pasku narzędzi.

  3. Wprowadź nazwę tematu. Pozostaw inne opcje z wartościami domyślnymi.

  4. Wybierz pozycję Utwórz.

    Screenshot of the Create topic page.

Tworzenie subskrypcji w temacie

  1. Wybierz temat utworzony w poprzedniej sekcji.

    Screenshot of the Topics page with your topic selected.

  2. Na stronie Temat usługi Service Bus wybierz pozycję Subskrypcje z menu po lewej stronie, a następnie wybierz pozycję + Subskrypcja na pasku narzędzi.

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

  3. Na stronie Tworzenie subskrypcji wykonaj następujące kroki:

    1. Wprowadź S1 jako nazwę subskrypcji.

    2. Następnie wybierz pozycję Utwórz , aby utworzyć subskrypcję.

      Screenshot of the Create subscription page.

  4. Powtórz poprzedni krok dwa razy, aby utworzyć subskrypcje o nazwach S2 i S3.

Tworzenie reguł filtrowania dla subskrypcji

Po aprowizowanej przestrzeni nazw i temacie/subskrypcjach masz parametry połączenia do przestrzeni nazw, możesz utworzyć reguły filtrowania w subskrypcjach, a następnie wysyłać i odbierać komunikaty. Kod można przeanalizować w tym folderze przykładów usługi GitHub.

Wysyłanie i odbieranie komunikatów

Aby uruchomić kod, wykonaj następujące kroki:

  1. W wierszu polecenia lub wierszu polecenia programu PowerShell sklonuj repozytorium GitHub usługi Service Bus, uruchamiając następujące polecenie:

    git clone https://github.com/Azure/azure-service-bus.git
    
  2. Przejdź do folderu przykładów azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters.

  3. Uzyskaj parametry połączenia skopiowaną do Notatnik wcześniej w tym samouczku. Potrzebna Ci będzie również nazwa tematu utworzonego w poprzedniej sekcji.

  4. W wierszu polecenia wpisz następujące polecenie:

    dotnet build
    
  5. Przejdź do folderu BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1.

  6. Wpisz następujące polecenie, aby uruchomić program. Pamiętaj, aby zastąpić myConnectionString wcześniej uzyskaną wartością, a myTopicName nazwą utworzonego przez siebie tematu:

    dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
    
  7. Postępuj zgodnie z instrukcjami w konsoli, aby najpierw wybrać tworzenie filtru. Tworzenie filtrów obejmuje usuwanie filtrów domyślnych. Jeśli używasz programu PowerShell lub interfejsu wiersza polecenia, nie musisz usuwać filtru domyślnego, ale jeśli to zrobisz w kodzie, musisz je usunąć. Polecenia konsoli 1 i 3 ułatwiają zarządzanie filtrami we wcześniej utworzonych subskrypcjach:

    • Wykonaj 1: aby usunąć filtry domyślne.

    • Wykonaj 2: aby dodać własne filtry.

    • Wykonaj 3. Pomiń ten krok na potrzeby samouczka. Ta opcja opcjonalnie usuwa własne filtry. Nie spowoduje ponownego utworzenia domyślnych filtrów.

      Showing output of 2

  8. Po utworzeniu filtra możesz wysyłać komunikaty. Naciśnij 4 i obserwuj wysyłanie 10 komunikatów do tematu:

    Send output

  9. Naciśnij 5 i obserwuj odbieranie komunikatów. Jeśli nie otrzymasz z powrotem 10 komunikatów, naciśnij przycisk "m", aby wyświetlić menu, a następnie naciśnij ponownie 5.

    Receive output

Czyszczenie zasobów

Jeśli zasoby nie będą już potrzebne, wykonaj następujące kroki, aby wyczyścić zasoby.

  1. Przejdź do przestrzeni nazw w witrynie Azure Portal.
  2. Na stronie Przestrzeń nazw usługi Service Bus wybierz pozycję Usuń na pasku poleceń, aby usunąć w niej przestrzeń nazw i zasoby (kolejki, tematy i subskrypcje).

Omówienie przykładowego kodu

Ta sekcja zawiera więcej szczegółów na temat operacji wykonywanych przez przykładowy kod.

Pobieranie parametrów połączenia i tematu

Najpierw w kodzie jest deklarowany zestaw zmiennych, które realizują pozostałe operacje programu.

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.

Parametry połączenia i nazwa tematu są przekazywane za pośrednictwem parametrów wiersza polecenia, jak to pokazano, a następnie odczytywane w metodzie 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();
    }
}

Usuwanie filtrów domyślnych

Podczas tworzenia subskrypcji usługa Service Bus tworzy filtr domyślny dla każdej subskrypcji. Ten filtr umożliwia odbieranie wszystkich komunikatów wysłanych do tematu. Jeśli chcesz używać filtrów niestandardowych, możesz usunąć filtr domyślny, jak pokazano w poniższym kodzie:

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

Tworzenie filtrów

Poniższy kod dodaje filtry niestandardowe zdefiniowane w tym samouczku:

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

Usuwanie utworzonych filtrów niestandardowych

Jeśli chcesz usunąć wszystkie filtry w ramach subskrypcji, poniższy kod pokazuje, jak to zrobić:

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

Wysyłanie komunikatów

Wysyłanie komunikatów do tematu przypomina wysyłanie komunikatów do kolejki. W tym przykładzie pokazano, jak wysyłać komunikaty z wykorzystaniem listy zadań i przetwarzania asynchronicznego:

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

Odbieranie komunikatów

Komunikaty są ponownie odbierane za pośrednictwem listy zadań, a kod korzysta z dzielenia na partie. Umożliwia wysyłanie i odbieranie z wykorzystaniem dzielenia na partie, ale w tym przykładzie pokazano tylko, jak odbierać partie. W rzeczywistości nie można przerwać pętli, ale zachować pętlę i ustawić wyższy przedział czasu, taki jak jedna minuta. Wywołanie odbierania do brokera jest utrzymywane przez ten czas otwarte i po odebraniu komunikatów zostanie zwrócone natychmiast i zostanie wysłane nowe wywołanie odbioru. To pojęcie jest nazywane długim sondowaniem. Użycie pompy odbioru, którą można zobaczyć w przewodniku Szybki start, a w kilku innych przykładach w repozytorium jest bardziej typową opcją.

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

Uwaga

Zasoby usługi Service Bus można zarządzać za pomocą Eksploratora usługi Service Bus. Eksplorator usługi Service Bus umożliwia użytkownikom łatwe łączenie się z przestrzenią nazw usługi Service Bus i administrowanie jednostkami obsługi komunikatów. Narzędzie udostępnia zaawansowane funkcje, takie jak funkcje importu/eksportu lub możliwość testowania tematu, kolejek, subskrypcji, usług przekazywania, centrów powiadomień i centrów zdarzeń.

Następne kroki

W tym samouczku zainicjowano zasoby przy użyciu witryny Azure Portal, a następnie wysłano i odebrano komunikaty z tematu usługi Service Bus i jego subskrypcji. W tym samouczku omówiono:

  • Tworzenie tematu usługi Service Bus i co najmniej jednej subskrypcji do tego tematu przy użyciu witryny Azure Portal
  • Dodawanie filtrów tematu przy użyciu kodu platformy .NET
  • Tworzenie dwóch komunikatów z różną zawartością
  • Wysyłanie komunikatów oraz sprawdzanie, czy dotarły do spodziewanych subskrypcji
  • Odbieranie komunikatów z subskrypcji

Więcej przykładów dotyczących wysyłania i odbierania komunikatów znajduje się w temacie Service Bus samples on GitHub (Przykłady dotyczące usługi Service Bus w serwisie GitHub).

Przejdź do następnego samouczka, aby dowiedzieć się więcej o korzystaniu z możliwości publikowania/subskrypcji usługi Service Bus.