Ćwiczenie — wysyłanie komunikatów między mikrousługami za pośrednictwem rabbitMQ

Ukończone

RabbitMQ to niezawodny broker komunikatów, który zapewnia elastyczne wymiany komunikatów i kolejki. Aby wysyłać i odbierać komunikaty za pośrednictwem programu RabbitMQ w projekcie .NET Aspire, należy dodać kontener RabbitMQ, a następnie utworzyć kod, który wysyła komunikaty z jednej mikrousługi i odbiera go w innej.

W tym ćwiczeniu wyślesz komunikaty do kolejki z projektu Catalog.API. Dodasz nowy projekt usługi w tle, który odbiera te komunikaty z kolejki i wysyła je do dziennika konsoli do wyświetlenia.

Instalacja wymagań wstępnych

Wymagania wstępne dotyczące platformy .NET Aspire są następujące:

  • .NET 8
  • Visual Studio 2022 (wersja zapoznawcza)
  • Docker Desktop lub Podman
  • Obciążenie .NET Aspire w programie Visual Studio

Jeśli masz już zainstalowane te pakiety, możesz przejść do przodu, aby rozpocząć pracę z RabbitMQ.

Instalowanie platformy .NET 8

Postępuj zgodnie z tym linkiem platformy .NET 8 i wybierz prawidłowy instalator dla swojego systemu operacyjnego. Jeśli na przykład używasz systemu Windows 11 i nowoczesnego procesora, wybierz zestaw SDK platformy .NET 8 x64 dla systemu Windows.

Po zakończeniu pobierania uruchom instalatora i postępuj zgodnie z instrukcjami. W oknie terminalu uruchom następujące polecenie, aby sprawdzić, czy instalacja zakończyła się pomyślnie:

dotnet --version

Powinien zostać wyświetlony numer wersji zainstalowanego zestawu .NET SDK. Na przykład:

8.0.300-preview.24203.14

Instalowanie programu Visual Studio 2022 (wersja zapoznawcza)

Postępuj zgodnie z tym linkiem programu Visual Studio 2022 (wersja zapoznawcza) i wybierz pozycję Pobierz wersję zapoznawcza. Po zakończeniu pobierania uruchom instalatora i postępuj zgodnie z instrukcjami.

Instalowanie programu Docker Desktop

Postępuj zgodnie z tym linkiem do programu Docker Desktop i wybierz prawidłowy instalator dla swojego systemu operacyjnego. Po zakończeniu pobierania uruchom instalatora i postępuj zgodnie z instrukcjami. Aby uzyskać najlepszą wydajność i zgodność, użyj zaplecza WSL 2.

Otwórz aplikację docker Desktop i zaakceptuj umowę serwisową.

Instalowanie obciążenia platformy .NET Aspire w programie Visual Studio

Zainstaluj obciążenie platformy .NET Aspire przy użyciu interfejsu wiersza polecenia platformy .NET:

  1. Otwórz terminal.

  2. Zaktualizuj obciążenia platformy .NET za pomocą tego polecenia:

    dotnet workload update
    

    Powinien zostać wyświetlony komunikat informujący o pomyślnym zaktualizowaniu obciążeń.

    No workloads installed for this feature band. To update workloads installed with earlier SDK versions, include the --from-previous-sdk option.
    Updated advertising manifest microsoft.net.sdk.ios.
    Updated advertising manifest microsoft.net.workload.mono.toolchain.net6.
    Updated advertising manifest microsoft.net.sdk.android.
    Updated advertising manifest microsoft.net.workload.emscripten.net7.
    Updated advertising manifest microsoft.net.workload.emscripten.net6.
    Updated advertising manifest microsoft.net.sdk.macos.
    Updated advertising manifest microsoft.net.workload.emscripten.current.
    Updated advertising manifest microsoft.net.workload.mono.toolchain.current.
    Updated advertising manifest microsoft.net.sdk.maui.
    Updated advertising manifest microsoft.net.workload.mono.toolchain.net7.
    Updated advertising manifest microsoft.net.sdk.maccatalyst.
    Updated advertising manifest microsoft.net.sdk.tvos.
    Updated advertising manifest microsoft.net.sdk.aspire.
    No workloads installed for this feature band. To update workloads installed with earlier SDK versions, include the --from-previous-sdk option.
    
    Successfully updated workload(s): .
    
  3. Zainstaluj obciążenie platformy .NET Aspire za pomocą tego polecenia:

    dotnet workload install aspire
    

    Powinien zostać wyświetlony komunikat informujący o zainstalowaniu obciążenia Aspire.

    Installing Aspire.Hosting.Sdk.Msi.x64 ...... Done
    Installing Aspire.ProjectTemplates.Msi.x64 ..... Done
    Installing Aspire.Hosting.Orchestration.win-x64.Msi.x64 ............. Done
    Installing Aspire.Hosting.Msi.x64 ..... Done
    Installing Aspire.Dashboard.Sdk.win-x64.Msi.x64 ....... Done
    
    Successfully installed workload(s) aspire.
    
  4. Sprawdź, czy obciążenie platformy .NET Aspire jest zainstalowane za pomocą tego polecenia:

    dotnet workload list
    

    Powinny zostać wyświetlone szczegóły obciążenia platformy .NET Aspire.

     Installed Workload Id      Manifest Version      Installation Source
    ---------------------------------------------------------------------------------------------
    aspire                     8.0.0/8.0.100         SDK 8.0.300-preview.24203, VS 17.10.34902.84
    
    Use `dotnet workload search` to find additional workloads to install.
    

Klonowanie projektu

Użyjmy metody git , aby uzyskać przykładową aplikację, która nie korzysta jeszcze z brokera komunikatów:

  1. W wierszu polecenia przejdź do wybranego folderu, w którym możesz pracować z kodem.

  2. Wykonaj następujące polecenie, aby sklonować przykładową aplikację:

    git clone -b aspire-rabbitmq  https://github.com/MicrosoftDocs/mslearn-aspire-starter
    

Tworzenie kontenera RabbitMQ

Zacznijmy od dodania programu RabbitMQ do projektu hosta aplikacji. Po uruchomieniu rozwiązania platforma .NET Aspire dodaje kontener RabbitMQ do aplikacji i przekazuje odwołania do projektów, które go używają:

  1. Uruchom program Visual Studio i wybierz pozycję Otwórz projekt lub rozwiązanie.

  2. Przejdź do folderu, w którym sklonował projekt.

  3. Kliknij dwukrotnie folder Start, wybierz rozwiązanie eShop.rabbitmq.sln, a następnie wybierz pozycję Otwórz.

  4. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt eShop.AppHost, wybierz pozycję Dodaj, a następnie wybierz pakiet .NET Aspire.

  5. W polu tekstowym wyszukiwania na końcu istniejącego tekstu wpisz RabbitMQ.

  6. Wybierz pakiet Aspire.Hosting.RabbitMQ .

  7. Na liście Wersja wybierz najnowszą wersję 8.0.0, a następnie wybierz pozycję Zainstaluj.

  8. Jeśli zostanie wyświetlone okno dialogowe Podgląd zmian, wybierz pozycję Zastosuj.

  9. W oknie dialogowym Akceptacja licencji wybierz pozycję Akceptuję.

  10. W Eksplorator rozwiązań rozwiń węzeł eShop.AppHost, a następnie kliknij dwukrotnie Program.cs.

  11. Znajdź następujący wiersz kodu:

    var builder = DistributedApplication.CreateBuilder(args);
    
  12. Natychmiast po tym kodzie, aby zarejestrować serwer RabbitMQ, dodaj następujący kod:

    var messaging = builder.AddRabbitMQ("messaging");
    
  13. Znajdź następujący kod, który rejestruje projekt Catalog.API dla orkiestracji platformy .NET Aspire:

    var catalogApi = builder.AddProject<Catalog_API>("catalog-api")
        .WithReference(catalogDb);
    
  14. Aby przekazać usługę RabbitMQ do projektu Catalog.API , zmień ten kod, aby był zgodny z tym kodem:

    var catalogApi = builder.AddProject<Catalog_API>("catalog-api")
        .WithReference(catalogDb)
        .WithReference(messaging);
    

Dodawanie biblioteki RabbitMQ do projektu Catalog.API

Teraz możemy zainstalować i skonfigurować aplikację RabbitMQ w projekcie Catalog.API:

  1. W programie Visual Studio w Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt Catalog.API, wybierz pozycję Dodaj, a następnie wybierz pakiet .NET Aspire.

  2. W polu tekstowym wyszukiwania na końcu istniejącego tekstu wpisz RabbitMQ.

  3. Wybierz pakiet Aspire.RabbitMQ.Client.

  4. Na liście Wersja wybierz najnowszą wersję 8.0.0, a następnie wybierz pozycję Zainstaluj.

  5. Jeśli zostanie wyświetlone okno dialogowe Podgląd zmian, wybierz pozycję Zastosuj.

  6. W oknie dialogowym Akceptacja licencji wybierz pozycję Akceptuję.

  7. W Eksplorator rozwiązań rozwiń projekt Catalog.API, a następnie kliknij dwukrotnie Program.cs.

  8. W pliku Program.cs znajdź następujący wiersz kodu:

    var builder = WebApplication.CreateBuilder(args);
    
  9. Natychmiast po tym wierszu, aby zarejestrować połączenie RabbitMQ, dodaj następujący kod:

    builder.AddRabbitMQClient("messaging");
    

Wysyłanie komunikatu do kolejki RabbitMQ

Gdy użytkownik żąda elementów w wykazie, chcemy wysłać komunikat do kolejki RabbitMQ, która opisuje szczegóły żądania. Dodajmy teraz ten kod:

  1. W Eksplorator rozwiązań rozwiń węzeł Catalog.API > Apis, a następnie kliknij dwukrotnie CatalogApi.cs.

  2. Znajdź następujący kod, który deklaruje metodę GetAllItems() :

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services)
    {
    
  3. Aby użyć iniekcji zależności w celu uzyskania połączenia z RabbitMQ, zmodyfikuj kod, aby był zgodny z następującymi wierszami:

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services,
        RabbitMQ.Client.IConnection connection)
    {
    
  4. Znajdź następujący wiersz kodu:

    var totalItems = await services.DbContext.CatalogItems
        .LongCountAsync();
    
  5. Natychmiast po tym wierszu, aby utworzyć kanał obsługi komunikatów RabbitMQ, dodaj następujący kod:

    var channel = connection.CreateModel();
    
  6. W następnym wierszu, aby utworzyć kolejkę komunikatów, dodaj następujący kod:

    channel.QueueDeclare(queue: "catalogEvents",
                         durable: false,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);
    
  7. W następnym wierszu, aby wysłać komunikat, dodaj następujący kod:

    var body = Encoding.UTF8.GetBytes("Getting all items in the catalog.");
    
    channel.BasicPublish(exchange: string.Empty,
                         routingKey: "catalogEvents",
     					 mandatory: false,
                         basicProperties: null,
                         body: body);
    

Dodawanie projektu odbiorcy komunikatów

Aby odbierać komunikaty z kolejki RabbitMQ, utwórzmy nowy projekt:

  1. W Eksplorator rozwiązań kliknij rozwiązanie prawym przyciskiem myszy, wskaż polecenie Dodaj, a następnie wybierz pozycję Nowy projekt.

  2. W polu tekstowym Wyszukaj szablony wpisz Konsola.

  3. Wybierz szablon Aplikacja konsolowa języka C#, a następnie wybierz pozycję Dalej.

  4. W polu tekstowym Nazwa projektu wpisz RabbitConsumer , a następnie wybierz przycisk Dalej.

  5. Na liście Framework upewnij się, że wybrano pozycję .NET 8.0, a następnie wybierz pozycję Utwórz.

  6. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt AppHost, wskaż polecenie Dodaj, a następnie wybierz pozycję Dokumentacja projektu.

  7. Na liście projektów upewnij się, że wybrano pozycję RabbitConsumer , a następnie wybierz przycisk OK.

    Zrzut ekranu przedstawiający sposób dodawania odwołania do projektu AppHost, który odwołuje się do projektu RabbitConsumer.

  8. W Eksplorator rozwiązań rozwiń węzeł AppHost, a następnie kliknij dwukrotnie Program.cs.

  9. Znajdź następujący kod:

    builder.AddProject<WebApp>("webapp")
        .WithReference(catalogApi);
    
  10. Natychmiast po tym kodzie, aby dodać projekt RabbitConsumer do orkiestracji .NET Aspire, dodaj następujący kod:

    builder.AddProject<Projects.RabbitConsumer>("consumers")
        .WithReference(messaging);
    

Konfigurowanie projektu odbiorcy komunikatów

Zanim będziemy mogli odbierać komunikaty w nowym projekcie odbiorcy komunikatów, musimy skonfigurować ją tak, aby korzystała z usługi tworzenia kopii zapasowej RabbitMQ z hosta AppHost:

  1. W programie Visual Studio w Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt RabbitConsumer, wybierz pozycję Dodaj, a następnie wybierz pakiet .NET Aspire.

  2. W polu tekstowym wyszukiwania na końcu istniejącego tekstu wpisz RabbitMQ.

  3. Wybierz pakiet Aspire.RabbitMQ.Client.

  4. Na liście Wersja wybierz najnowszą wersję 8.0.0, a następnie wybierz pozycję Zainstaluj.

  5. Jeśli zostanie wyświetlone okno dialogowe Podgląd zmian, wybierz pozycję Zastosuj.

  6. W oknie dialogowym Akceptacja licencji wybierz pozycję Akceptuję.

  7. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt RabbitConsumer, wskaż polecenie Dodaj, a następnie wybierz pozycję Dokumentacja projektu.

  8. Na liście projektów upewnij się, że wybrano pozycję eShop.ServiceDefaults , a następnie wybierz przycisk OK.

    Zrzut ekranu przedstawiający sposób dodawania odwołania do projektu RabbitConsumer, który odwołuje się do projektu ServiceDefaults.

  9. W Eksplorator rozwiązań rozwiń projekt RabbitConsumer, a następnie kliknij dwukrotnie Program.cs.

  10. Usuń cały kod domyślny i zastąp go następującymi wierszami:

    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    var builder = Host.CreateApplicationBuilder(args);
    
    builder.AddServiceDefaults();
    
    builder.AddRabbitMQClient("messaging");
    
    var host = builder.Build();
    
    host.Run();
    

    Zwróć uwagę, że kod używa orkiestracji platformy .NET Aspire, aby dodać usługę RabbitMQ do projektu odbiorcy. Ta usługa będzie używana do pobierania komunikatów.

Odbieranie komunikatu RabbitMQ

Aby otrzymać komunikat, musimy utworzyć składnik, który działa w tle czekając na nadejście komunikatów. BackgroundService Użyj klasy dla tego zadania:

  1. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt RabbitConsumer, wskaż polecenie Dodaj, a następnie wybierz pozycję Klasa.

  2. W polu tekstowym Nazwa wpisz CatalogProcessingJob , a następnie wybierz pozycję Dodaj.

  3. W klasie CatalogProcessingJob.cs usuń cały kod domyślny i zastąp go następującymi wierszami:

     namespace RabbitConsumer;
    
    using System.Text;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using RabbitMQ.Client;
    using RabbitMQ.Client.Events;
    
    public class CatalogProcessingJob : BackgroundService
    {
        private readonly ILogger<CatalogProcessingJob> _logger;
        private readonly IConfiguration _config;
        private readonly IServiceProvider _serviceProvider;
        private IConnection? _messageConnection;
        private IModel? _messageChannel;
     	private EventingBasicConsumer consumer;
    
        public CatalogProcessingJob(ILogger<CatalogProcessingJob> logger, IConfiguration config, IServiceProvider serviceProvider, IConnection? messageConnection)
        {
            _logger = logger;
            _config = config;
            _serviceProvider = serviceProvider;
        }
    
        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            string queueName = "catalogEvents";
    
            _messageConnection = _serviceProvider.GetRequiredService<IConnection>();
    
            _messageChannel = _messageConnection.CreateModel();
            _messageChannel.QueueDeclare(queue: queueName,
                durable: false,
                exclusive: false,
                autoDelete: false,
                arguments: null);
    
            consumer = new EventingBasicConsumer(_messageChannel);
            consumer.Received += ProcessMessageAsync;
    
            _messageChannel.BasicConsume(queue:  queueName,
                autoAck: true, 
                consumer: consumer);
    
            return Task.CompletedTask;
        }
    
        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            await base.StopAsync(cancellationToken);
            consumer.Received -= ProcessMessageAsync;
            _messageChannel?.Dispose();
        }
    
        private void ProcessMessageAsync(object? sender, BasicDeliverEventArgs args)
        {
    
            string messagetext = Encoding.UTF8.GetString(args.Body.ToArray());
            _logger.LogInformation("All products retrieved from the catalog at {now}. Message Text: {text}", DateTime.Now, messagetext);
    
            var message = args.Body;
        }
    }
    
  4. W Eksplorator rozwiązań w projekcie RabbitConsumer kliknij dwukrotnie Program.cs.

  5. Znajdź następujący kod:

    builder.AddRabbitMQClient("messaging");
    
  6. Natychmiast po tym wierszu dodaj następujący kod:

    builder.Services.AddHostedService<CatalogProcessingJob>();
    

Testowanie rozwiązania

Przetestujmy naszą usługę tworzenia kopii zapasowych RabbitMQ i mikrousługi, które wysyłają i odbierają komunikaty:

  1. W programie Visual Studio, aby uruchomić aplikację w trybie debugowania, naciśnij F5 lub wybierz pozycję Debuguj > Rozpocznij debugowanie.

  2. Jeśli zostanie wyświetlony komunikat Uruchom program Docker Desktop, wybierz pozycję Tak. Aplikacja uruchamia się i wyświetla pulpit nawigacyjny platformy .NET Aspire na karcie przeglądarki.

  3. Na pulpicie nawigacyjnym platformy .NET Aspire na liście Zasobów zwróć uwagę, że lista zawiera nowy kontener z nazwą messaging. Źródło zawiera rabbitmq:3. Ten kontener uruchamia brokera komunikatów RabbitMQ.

    Zrzut ekranu przedstawiający kontener RabbitMQ wyświetlany na pulpicie nawigacyjnym platformy .NET Aspire.

  4. W obszarze nawigacji po lewej stronie wybierz pozycję Konsola.

  5. Na liście Wybierz zasób wybierz pozycję Obsługa komunikatów. Na stronie zostaną wyświetlone dzienniki konsoli brokera RabbitMQ. Zwróć uwagę, że ostatnie kilka komunikatów wskazuje, że RabbitMQ zakończyła uruchamianie i zaakceptowała jedno połączenie. To połączenie pochodzi z odbierającego projektu RabbitConsumer .

  6. W obszarze nawigacji po lewej stronie wybierz pozycję Zasoby.

  7. W wierszu projektu aplikacji internetowej w kolumnie Punkty końcowe wybierz jeden z linków. Zostanie otwarta strona główna firmy Northern Traders i zostanie wyświetlony katalog produktów. Ta strona wysyła komunikat do kolejki RabbitMQ.

    Zrzut ekranu przedstawiający sposób uzyskiwania dostępu do punktu końcowego projektu WebApp z poziomu pulpitu nawigacyjnego platformy .NET Aspire.

  8. Wróć do pulpitu nawigacyjnego platformy .NET Aspire. W obszarze nawigacji po lewej stronie wybierz pozycję Konsola.

  9. Na liście Wybierz zasób wybierz pozycję Obsługa komunikatów. Zwróć uwagę, że RabbitQ zaakceptował drugie połączenie. To połączenie pochodzi z projektu Catalog.API .

  10. Na liście Wybierz zasób wybierz użytkowników. Ten dziennik jest przeznaczony dla projektu RabbitConsumer . Ostatni wpis wyświetla komunikat "Pobieranie wszystkich elementów w wykazie". Ten komunikat został pobrany z rabbitMQ i zarejestrowany.

    Zrzut ekranu przedstawiający komunikat pobrany z kolejki RabbitMQ i wyświetlony w dziennikach konsoli projektu odbiorcy.