Ćwiczenie — wysyłanie i odbieranie komunikatów przy użyciu kolejki

Ukończone

Wybrano użycie kolejki usługi Service Bus do obsługi komunikatów dotyczących sprzedaży indywidualnej między aplikacją mobilną, której używa personel sprzedaży, a usługą internetową hostowaną na platformie Azure, która przechowuje szczegółowe informacje o każdej sprzedaży w wystąpieniu usługi Azure SQL Database.

W poprzednim ćwiczeniu zaimplementowano niezbędne obiekty w ramach subskrypcji platformy Azure. Teraz chcesz napisać kod, który wysyła komunikaty do tej kolejki i je pobiera.

W tej lekcji utworzysz dwie aplikacje konsolowe: jedna aplikacja umieszcza komunikaty w kolejce usługi Service Bus, a jedna aplikacja pobiera komunikaty z kolejki usługi Service Bus. Te aplikacje są częścią jednego rozwiązania platformy .NET Core.

Pobieranie parametry połączenia do przestrzeni nazw usługi Service Bus

Aby uzyskać dostęp do przestrzeni nazw usługi Service Bus i użyć kolejki w tej przestrzeni nazw, należy skonfigurować dwie informacje w dwóch aplikacjach konsoli:

  • Punkt końcowy dla przestrzeni nazw
  • Klucz dostępu współdzielonego na potrzeby uwierzytelniania

Te wartości można pobrać z parametry połączenia.

  1. W oknie usługi Cloud Shell po prawej stronie ekranu wybierz ikonę Więcej (...), a następnie wybierz pozycję Ustawienia>Przejdź do wersji klasycznej.

  2. Uruchom następujące polecenie, zastępując <namespace-name> ciąg przestrzenią nazw usługi Service Bus utworzoną w ostatnim ćwiczeniu.

    az servicebus namespace authorization-rule keys list \
        --resource-group "<rgn>[sandbox resource group name]</rgn>" \
        --name RootManageSharedAccessKey \
        --query primaryConnectionString \
        --output tsv \
        --namespace-name <namespace-name>
    

    Ostatnim wierszem odpowiedzi jest parametry połączenia, który zawiera punkt końcowy przestrzeni nazw i klucz dostępu współdzielonego. Powinien on przypominać następujący przykład:

    Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxxxx
    
  3. Skopiuj parametry połączenia z usługi Cloud Shell. Ten parametry połączenia będzie potrzebny kilka razy w tym module, więc warto zapisać go gdzieś przydatne.

Klonowanie i otwieranie aplikacji startowej

Uwaga

Dla uproszczenia następujące zadania zawierają instrukcje dotyczące kodowania parametry połączenia w pliku Program.cs obu aplikacji konsolowych. W aplikacji produkcyjnej należy użyć pliku konfiguracji lub usługi Azure Key Vault do przechowywania parametry połączenia.

  1. Uruchom następujące polecenie w usłudze Cloud Shell, aby sklonować rozwiązanie projektu Git:

    cd ~
    git clone https://github.com/MicrosoftDocs/mslearn-connect-services-together.git
    
  2. Uruchom następujące polecenie, aby przejść do folderu startowego w sklonowanym projekcie i otworzyć edytor usługi Cloud Shell:

    cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
    code .
    

Pisanie kodu w celu wysłania komunikatu do kolejki

  1. W edytorze usługi Cloud Shell otwórz plik privatemessagesender/Program.cs i znajdź następujący wiersz kodu:

    const string ServiceBusConnectionString = "";
    

    Wklej parametry połączenia między znakami cudzysłowu.

  2. Jeśli użyto nazwy innej niż salesmessages dla nazwy kolejki, zaktualizuj wartość właściwości QueueName w kodzie:

    const string QueueName = "salesmessages";
    
  3. Aby ukończyć składnik, który wysyła komunikaty dotyczące sprzedaży, należy dodać await operatora w celu wstrzymania oceny metody asynchronicznej do momentu zakończenia operacji asynchronicznej. Znajdź metodę SendSalesMessageAsync() . W ramach tej metody znajdź następujący wiersz kodu:

    // Create a Service Bus client here
    

    Zastąp ten wiersz kodu następującym kodem:

    // By leveraging "await using", the DisposeAsync method will be called automatically once the client variable goes out of scope. 
    // In more realistic scenarios, you would want to store off a class reference to the client (rather than a local variable) so that it can be used throughout your program.
    
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. W metodzie SendSalesMessageAsync() znajdź następujący wiersz kodu:

    // Create a sender here
    

    Zastąp ten komentarz następującym kodem:

    await using ServiceBusSender sender = client.CreateSender(QueueName);
    
  5. try...catch W bloku znajdź następujący wiersz kodu:

    // Create and send a message here
    

    Zastąp ten wiersz kodu następującymi wierszami kodu:

    string messageBody = $"$10,000 order for bicycle parts from retailer Adventure Works.";
    var message = new ServiceBusMessage(messageBody);
    
  6. Wstaw następujący kod w nowym wierszu bezpośrednio poniżej tego, co właśnie dodano, aby wyświetlić komunikat w konsoli programu :

    Console.WriteLine($"Sending message: {messageBody}");
    
  7. Wstaw następujący kod w następnym wierszu:

    await sender.SendMessageAsync(message);
    
  8. Aby usunąć obiekty nadawcy i klienta, na końcu pliku znajdź następujący komentarz:

    // Close the connection to the sender here
    

    Zastąp wiersz następującym kodem:

    finally
    {
        // Calling DisposeAsync on client types is required to ensure that network
        // resources and other unmanaged objects are properly cleaned up.
        await sender.DisposeAsync();
        await client.DisposeAsync();
    }
    
  9. Sprawdź, czy ostatni kod privatemessagesender/Program.cs przypomina następujący przykład:

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace privatemessagesender
    {
        class Program
        {
            const string ServiceBusConnectionString = "Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx";
            const string QueueName = "salesmessages";
    
            static void Main(string[] args)
            {
                Console.WriteLine("Sending a message to the Sales Messages queue...");
                SendSalesMessageAsync().GetAwaiter().GetResult();
                Console.WriteLine("Message was sent successfully.");
            }
    
            static async Task SendSalesMessageAsync()
            {
                await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
                await using ServiceBusSender sender = client.CreateSender(QueueName);
                try
                {
                    string messageBody = $"$10,000 order for bicycle parts from retailer Adventure Works.";
                    var message = new ServiceBusMessage(messageBody);
                    Console.WriteLine($"Sending message: {messageBody}");
                    await sender.SendMessageAsync(message);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
                }
                finally
                {
                    // Calling DisposeAsync on client types is required to ensure that network
                    // resources and other unmanaged objects are properly cleaned up.
                    await sender.DisposeAsync();
                    await client.DisposeAsync();
                }
            }
        }
    }
    
  10. Aby zapisać zmiany, naciśnij klawisze Ctrl+S, a następnie naciśnij klawisze Ctrl+Q, aby zamknąć edytor.

Wysyłanie komunikatu do kolejki

  1. W usłudze Cloud Shell uruchom następujące polecenie, aby wysłać komunikat dotyczący sprzedaży. Pierwszy wiersz gwarantuje, że jesteś we właściwej ścieżce.

    cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
    dotnet run --project ./privatemessagesender
    

    Uwaga

    Przy pierwszym uruchomieniu aplikacji w tym ćwiczeniu można dotnet przywrócić pakiety ze źródeł zdalnych i skompilować aplikacje.

    W miarę uruchamiania programu komunikaty są drukowane w konsoli, co oznacza, że aplikacja wysyła komunikat:

    Sending a message to the Sales Messages queue...
    Sending message: $10,000 order for bicycle parts from retailer Adventure Works.
    Message was sent successfully.
    
  2. Po zakończeniu działania aplikacji uruchom następujące polecenie, zastępując <przestrzeń nazw nazwą przestrzeni nazw> usługi Service Bus. To polecenie zwraca liczbę komunikatów w kolejce.

    az servicebus queue show \
        --resource-group "<rgn>[sandbox resource group name]</rgn>" \
        --name salesmessages \
        --query messageCount \
        --namespace-name <namespace-name>
    
  3. dotnet run Uruchom ponownie polecenie z kroku 1, a następnie ponownie uruchom servicebus queue show polecenie. Za każdym razem, gdy uruchamiasz aplikację dotnet, do kolejki jest dodawany nowy komunikat. Zobaczysz messageCount wzrost za każdym razem, gdy uruchomisz polecenie platformy Azure.

Pisanie kodu w celu odbierania komunikatów z kolejki

  1. Uruchom następujące polecenie, aby ponownie otworzyć edytor:

    code .
    
  2. W edytorze otwórz plik privatemessagereceiver/Program.cs i znajdź następujący wiersz kodu:

    const string ServiceBusConnectionString = "";
    

    Między znakami cudzysłowu wklej zapisany wcześniej parametry połączenia.

  3. Znajdź metodę ReceiveSalesMessageAsync() . W ramach tej metody znajdź następujący wiersz kodu:

    // Create a Service Bus client that will authenticate using a connection string
    

    Zastąp wiersz następującym kodem:

    var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. Aby skonfigurować opcje obsługi komunikatów, znajdź następujący wiersz kodu:

    // Create the options to use for configuring the processor
    

    Zastąp ten wiersz następującymi wierszami kodu:

    var processorOptions = new ServiceBusProcessorOptions
    {
        MaxConcurrentCalls = 1,
        AutoCompleteMessages = false
    };
    
  5. Aby utworzyć procesor, znajdź następujący wiersz kodu:

    // Create a processor that we can use to process the messages
    

    Zastąp wiersz następującym kodem:

    await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);
    
  6. Aby skonfigurować programy obsługi, znajdź następujący wiersz kodu:

    // Configure the message and error handler to use
    

    Zastąp wiersz następującym kodem:

    processor.ProcessMessageAsync += MessageHandler;
    processor.ProcessErrorAsync += ErrorHandler;
    
  7. Aby rozpocząć przetwarzanie, znajdź następujący wiersz kodu:

    // Start processing
    

    Zastąp wiersz następującym kodem:

    await processor.StartProcessingAsync();
    
  8. Aby zamknąć połączenie z usługą Service Bus, znajdź następujący wiersz kodu:

    // Close the processor here
    

    Zastąp wiersz następującym kodem:

    await processor.CloseAsync();
    
  9. Przejrzyj kod w metodzie MessageHandler :

    // handle received messages
    static async Task MessageHandler(ProcessMessageEventArgs args)
    {
        // extract the message
        string body = args.Message.Body.ToString();
    
        // print the message
        Console.WriteLine($"Received: {body}");
    
        // complete the message so that message is deleted from the queue. 
        await args.CompleteMessageAsync(args.Message);
    }
    
  10. Przejrzyj kod w metodzie ErrorHandler :

    // handle any errors when receiving messages
    static Task ErrorHandler(ProcessErrorEventArgs args)
    {
        // print the exception message
        Console.WriteLine(args.Exception.ToString());
        return Task.CompletedTask;
    }    
    
  11. Sprawdź, czy ostatni kod privatemessagereceiver/Program.cs przypomina następujący przykład:

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace privatemessagereceiver
    {
        class Program
        {
    
            const string ServiceBusConnectionString = "Endpoint=sb://<examplenamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            const string QueueName = "salesmessages";
    
            static void Main(string[] args)
            {
    
                ReceiveSalesMessageAsync().GetAwaiter().GetResult();
    
            }
    
            static async Task ReceiveSalesMessageAsync()
            {
    
                Console.WriteLine("======================================================");
                Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
                Console.WriteLine("======================================================");
    
    
                var client = new ServiceBusClient(ServiceBusConnectionString);
    
                var processorOptions = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = 1,
                    AutoCompleteMessages = false
                };
    
                await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);
    
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync += ErrorHandler;
    
    
                await processor.StartProcessingAsync();
    
                Console.Read();
    
                await processor.CloseAsync();
    
            }
    
            // handle received messages
            static async Task MessageHandler(ProcessMessageEventArgs args)
            {
                string body = args.Message.Body.ToString();
                Console.WriteLine($"Received: {body}");
    
                // complete the message. messages is deleted from the queue. 
                await args.CompleteMessageAsync(args.Message);
            }
    
            // handle any errors when receiving messages
            static Task ErrorHandler(ProcessErrorEventArgs args)
            {
                Console.WriteLine(args.Exception.ToString());
                return Task.CompletedTask;
            }
        }
    }
    
    
  12. Aby zapisać zmiany, naciśnij klawisze Ctrl+S, a następnie naciśnij klawisze Ctrl+Q, aby zamknąć edytor.

Odbieranie komunikatu z kolejki

  1. Aby uruchomić składnik, który otrzymuje komunikat o sprzedaży, uruchom to polecenie w usłudze Cloud Shell:

    dotnet run --project privatemessagereceiver
    
  2. Sprawdź powiadomienia w usłudze Cloud Shell. W witrynie Azure Portal przejdź do przestrzeni nazw usługi Service Bus i sprawdź wykres Komunikaty :

    Received: $10,000 order for bicycle parts from retailer Adventure Works.
    
  3. Gdy zobaczysz, że komunikaty zostały odebrane w usłudze Cloud Shell, naciśnij Enter , aby zatrzymać aplikację.

Sprawdzanie liczby komunikatów

Uruchom następujący kod, aby potwierdzić, że wszystkie komunikaty zostały usunięte z kolejki, pamiętając o zastąpieniu <przestrzeni nazw przestrzenią nazw> usługi Service Bus.

az servicebus queue show \
    --resource-group "<rgn>[sandbox resource group name]</rgn>" \
    --name salesmessages \
    --query messageCount \
    --namespace-name <namespace-name>

Dane wyjściowe będą miały 0 wartość , jeśli wszystkie komunikaty zostały usunięte.

Napisałeś kod, który wysyła komunikat dotyczący sprzedaży indywidualnej do kolejki usługi Service Bus. W aplikacji rozproszonej salesforce należy napisać ten kod w aplikacji mobilnej używanej przez pracowników działu sprzedaży na urządzeniach.

Napisaliśmy również kod, który odbiera komunikat z kolejki usługi Service Bus. W aplikacji rozproszonej salesforce należy napisać ten kod w usłudze internetowej działającej na platformie Azure i przetwarzać odebrane komunikaty.