Esercizio - Inviare messaggi tra microservizi tramite RabbitMQ

Completato

RabbitMQ è un broker di messaggi affidabile che fornisce scambi di messaggi e code flessibili. Per inviare e ricevere messaggi tramite RabbitMQ in un progetto .NET Aspire, è necessario aggiungere un contenitore RabbitMQ, quindi creare codice che invia messaggi da un microservizio e che li riceve in un altro.

In questo esercizio si invieranno messaggi a una coda dal progetto Catalog.API. Si aggiungerà un nuovo progetto di servizi in background che riceve tali messaggi dalla coda e li invia al log della console per la visualizzazione.

Installare i prerequisiti

I prerequisiti per .NET Aspire sono:

  • .NET 8
  • Anteprima di Visual Studio 2022
  • Docker Desktop o Podman
  • Carico di lavoro .NET Aspire in Visual Studio

Se questi pacchetti sono già stati installati, è possibile iniziare a usare a lavorare con RabbitMQ.

Installare .NET 8

Seguire questo collegamento a .NET 8 e selezionare il programma di installazione corretto per il sistema operativo. Ad esempio, se si usa Windows 11 e un processore moderno, selezionare x64 .NET 8 SDK per Windows.

Al termine del download, eseguire il programma di installazione e seguire le istruzioni. In una finestra del terminale eseguire il comando seguente per verificare che l'installazione sia riuscita:

dotnet --version

Verrà visualizzato il numero di versione di .NET SDK installato. Ad esempio:

8.0.300-preview.24203.14

Installare Visual Studio 2022 Preview

Seguire questo collegamento di Visual Studio 2022 Preview e selezionare Scarica anteprima. Al termine del download, eseguire il programma di installazione e seguire le istruzioni.

Installare Docker Desktop

Seguire questo collegamento a Docker Desktop e selezionare il programma di installazione corretto per il sistema operativo. Al termine del download, eseguire il programma di installazione e seguire le istruzioni. Per ottenere prestazioni e compatibilità ottimali, usare il back-end WSL 2.

Aprire l'applicazione Docker Desktop e accettare il contratto di servizio.

Installare il carico di lavoro .NET Aspire in Visual Studio

Installare il carico di lavoro .NET Aspire usando l'interfaccia della riga di comando di .NET:

  1. Aprire un terminale.

  2. Aggiornare i carichi di lavoro .NET con questo comando:

    dotnet workload update
    

    Verrà visualizzato un messaggio che informa che i carichi di lavoro vengono aggiornati correttamente.

    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. Installare il carico di lavoro .NET Aspire con questo comando:

    dotnet workload install aspire
    

    Verrà visualizzato un messaggio che informa che il carico di lavoro Aspire è installato.

    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. Verificare che il carico di lavoro .NET Aspire sia installato con questo comando:

    dotnet workload list
    

    Verranno visualizzati i dettagli del carico di lavoro .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.
    

Clonare il progetto

Si userà git per ottenere un'app di esempio, che non usa ancora un broker di messaggi:

  1. Nella riga di comando passare a una cartella di propria scelta in cui è possibile usare il codice.

  2. Eseguire il comando seguente per clonare l'applicazione di esempio:

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

Creare il contenitore RabbitMQ

Per iniziare, aggiungere RabbitMQ al progetto host dell'app. Quando si avvia la soluzione, .NET Aspire aggiunge un contenitore RabbitMQ all'app e passa i riferimenti ai progetti che lo usano:

  1. Avviare Visual Studio e selezionare Apri un progetto o una soluzione.

  2. Spostarsi nella cartella in cui è stato clonato il progetto.

  3. Fare doppio clic sulla cartella avvia, selezionare la soluzione eShop.rabbitmq.sln, quindi selezionare Apri.

  4. In Esplora soluzioni, fai clic con il pulsante destro del mouse sul progetto eShop.AppHost, seleziona Aggiungi e quindi seleziona il pacchetto .NET Aspire.

  5. Nella casella di testo di ricerca digitare RabbitMQ alla fine del testo esistente.

  6. Selezionare il pacchetto Aspire.Hosting.RabbitMQ.

  7. Nell'elenco Versione, selezionare la versione 8.0.0 più recente e quindi selezionare Installa.

  8. Se viene visualizzata la finestra di dialogo Anteprima modifiche, selezionare Apply.

  9. Nella finestra di dialogo Accettazione della licenza selezionare Accetto.

  10. In Esplora soluzioni, espandere eShop.AppHost e quindi fare doppio clic su Program.cs.

  11. Individuare la riga di codice seguente:

    var builder = DistributedApplication.CreateBuilder(args);
    
  12. Subito dopo tale codice, per registrare un server RabbitMQ, aggiungere questo codice:

    var messaging = builder.AddRabbitMQ("messaging");
    
  13. Individuare il codice seguente, che registra il progetto Catalog.API per l'orchestrazione .NET Aspire:

    var catalogApi = builder.AddProject<Catalog_API>("catalog-api")
        .WithReference(catalogDb);
    
  14. Per passare il servizio RabbitMQ al progetto Catalog.API, modificare tale codice in modo che corrisponda al codice seguente:

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

Aggiungere RabbitMQ al progetto Catalog.API

È ora possibile installare e configurare RabbitMQ nel progetto Catalog.API:

  1. In Esplora soluzioni in Visual Studio fare clic con il pulsante destro del mouse sul progetto Catalog.API, scegliere Aggiungi e quindi selezionare pacchetto .NET Aspira.

  2. Nella casella di testo di ricerca digitare RabbitMQ alla fine del testo esistente.

  3. Selezionare il pacchetto Aspire.RabbitMQ.Client.

  4. Nell'elenco Versione, selezionare la versione 8.0.0 più recente e quindi selezionare Installa.

  5. Se viene visualizzata la finestra di dialogo Anteprima modifiche, selezionare Apply.

  6. Nella finestra di dialogo Accettazione della licenza selezionare Accetto.

  7. In Esplora soluzioni, espandere il progetto Catalog.API e quindi fare doppio clic su Program.cs.

  8. Nel file Program.cs individuare la riga di codice seguente:

    var builder = WebApplication.CreateBuilder(args);
    
  9. Subito dopo tale riga, per registrare la connessione RabbitMQ, aggiungere questo codice:

    builder.AddRabbitMQClient("messaging");
    

Inviare un messaggio a una coda RabbitMQ

Quando un utente richiede gli elementi nel catalogo, si vuole inviare un messaggio a una coda RabbitMQ che descrive i dettagli della richiesta. Ora si aggiunge il codice:

  1. In Esplora soluzioni espandere Catalog.API > API e quindi fare doppio clic su CatalogApi.cs.

  2. Individuare il codice seguente, che dichiara il metodo GetAllItems():

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services)
    {
    
  3. Per usare l'inserimento delle dipendenze e ottenere la connessione a RabbitMQ, modificare il codice in modo che corrisponda alle righe seguenti:

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services,
        RabbitMQ.Client.IConnection connection)
    {
    
  4. Individuare la riga di codice seguente:

    var totalItems = await services.DbContext.CatalogItems
        .LongCountAsync();
    
  5. Subito dopo tale riga, per creare un canale di messaggistica RabbitMQ, aggiungere questo codice:

    var channel = connection.CreateModel();
    
  6. Nella riga successiva aggiungere questo codice per creare una coda di messaggi:

    channel.QueueDeclare(queue: "catalogEvents",
                         durable: false,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);
    
  7. Nella riga successiva aggiungere il codice seguente per inviare il messaggio:

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

Aggiungere un progetto consumer messaggi

Per ricevere messaggi dalla coda RabbitMQ, creare un nuovo progetto:

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla soluzione, quindi su Aggiungi e selezionare Nuovo progetto.

  2. Nella casella di testo Cerca modelli digitare Console.

  3. Selezionare il modello App console C#, quindi selezionare Avanti.

  4. Nella casella di testo Nome progetto digitare RabbitConsumer, quindi selezionare Avanti.

  5. Nell'elenco Framework verificare che sia selezionato .NET 8.0, quindi selezionare Crea.

  6. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto AppHost, scegliere Aggiungi, quindi selezionare Riferimento progetto.

  7. Nell'elenco dei progetti assicurarsi che sia selezionato RabbitConsumer, quindi selezionare OK.

    Screenshot che mostra come aggiungere un riferimento al progetto AppHost che fa riferimento al progetto RabbitConsumer.

  8. In Esplora soluzioni, espandere AppHost e quindi fare doppio clic su Program.cs.

  9. Individuare il seguente codice:

    builder.AddProject<WebApp>("webapp")
        .WithReference(catalogApi);
    
  10. Subito dopo tale codice, per aggiungere il progetto RabbitConsumer all'orchestrazione .NET Aspire, aggiungere il codice seguente:

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

Configurare il progetto consumer messaggi

Prima di poter ricevere messaggi nel nuovo progetto consumer messaggi, è necessario configurarlo per l'uso del servizio di backup RabbitMQ di AppHost:

  1. In Visual Studio, in Esplora soluzioni, fai clic con il pulsante destro del mouse sul progetto RabbitConsumer, seleziona Aggiungi e quindi seleziona il pacchetto .NET Aspire.

  2. Nella casella di testo di ricerca digitare RabbitMQ alla fine del testo esistente.

  3. Selezionare il pacchetto Aspire.RabbitMQ.Client.

  4. Nell'elenco Versione, selezionare la versione 8.0.0 più recente e quindi selezionare Installa.

  5. Se viene visualizzata la finestra di dialogo Anteprima modifiche, selezionare Apply.

  6. Nella finestra di dialogo Accettazione della licenza selezionare Accetto.

  7. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto RabbitConsumer, scegliere Aggiungi, quindi selezionare Riferimento progetto.

  8. Nell'elenco dei progetti assicurarsi che sia selezionato eShop.ServiceDefaults, quindi selezionare OK.

    Screenshot che mostra come aggiungere un riferimento al progetto RabbitConsumer che fa riferimento al progetto ServiceDefaults.

  9. In Esplora soluzioni, espandere il progetto RabbitConsumer e quindi fare doppio clic su Program.cs.

  10. Rimuovere tutto il codice predefinito e sostituirlo con le righe seguenti:

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

    Si noti che il codice usa l'orchestrazione .NET Aspire per aggiungere il servizio RabbitMQ al progetto consumer. Questo servizio verrà usato per recuperare i messaggi.

Ricevere un messaggio RabbitMQ

Per ricevere un messaggio è necessario creare un'integrazione che venga eseguita in background in attesa dell'arrivo dei messaggi. Usare una classe BackgroundService per questa attività:

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto RabbitConsumer, scegliere Aggiungi, quindi selezionare Classe.

  2. Nella casella di testo Nome digitare CatalogProcessingJob, quindi selezionare Aggiungi.

  3. Nella classe CatalogProcessingJob.cs rimuovere tutto il codice predefinito e sostituirlo con le righe seguenti:

     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. In Esplora soluzioni, nel progetto RabbitConsumer fare doppio clic su Program.cs.

  5. Individuare il seguente codice:

    builder.AddRabbitMQClient("messaging");
    
  6. Subito dopo tale riga, aggiungere il codice seguente:

    builder.Services.AddHostedService<CatalogProcessingJob>();
    

Test della soluzione

Testare il servizio di backup RabbitMQ e i microservizi che inviano e ricevono messaggi:

  1. In Visual Studio, per avviare l'app in modalità di debug, premere F5 o selezionare Debug > Avvia debug.

  2. Se viene visualizzato il messaggio Avvia Docker Desktop, selezionare . L'app avvia e visualizza il dashboard .NET Aspire in una scheda del browser.

  3. Nel dashboard .NET Aspire, nell'elenco delle Risorse, si noti che è incluso un nuovo contenitore con il nome messaggistica. L'origine include rabbitmq:3. Questo contenitore esegue il broker di messaggi RabbitMQ.

    Screenshot che mostra un contenitore RabbitMQ visualizzato nel dashboard .NET Aspire.

  4. Nel riquadro di spostamento a sinistra selezionare Console.

  5. Nell'elenco Seleziona una risorsa selezionare messaggistica. Nella pagina vengono visualizzati i log della console per il broker RabbitMQ. Si noti che gli ultimi messaggi indicano che RabbitMQ ha completato l'avvio e ha accettato una connessione. Questa connessione proviene dal progetto RabbitConsumer ricevente.

  6. Nel riquadro di spostamento a sinistra selezionare Risorse.

  7. Nella riga del progetto app Web selezionare uno dei collegamenti nella colonna Endpoint. La home page di Northern Traders si apre e mostra il catalogo prodotti. Questa pagina invia un messaggio alla coda RabbitMQ.

    Screenshot che mostra come accedere all'endpoint del progetto WebApp dal dashboard .NET Aspire.

  8. Tornare al dashboard .NET Aspire. Nel riquadro di spostamento a sinistra selezionare Console.

  9. Nell'elenco Seleziona una risorsa selezionare messaggistica. Si noti che RabbitQ ha accettato una seconda connessione. Questa connessione proviene dal progetto Catalog.API.

  10. Nell'elenco Seleziona una risorsa selezionare consumer. Questo log fa riferimento al progetto RabbitConsumer. La voce finale mostra il messaggio "Recupero di tutti gli elementi del catalogo". Questo messaggio è stato recuperato da RabbitMQ e registrato.

    Screenshot che mostra il messaggio recuperato dalla coda RabbitMQ e visualizzato nei log della console del progetto consumer.