練習 - 透過 RabbitMQ 在微服務之間傳送訊息

已完成

RabbitMQ 是一個可靠的訊息代理程式,可提供彈性的傳訊交換和佇列。 若要透過 .NET Aspire 專案中的 RabbitMQ 傳送和接收訊息,您必須新增 RabbitMQ 容器,然後建立程式碼以從一個微服務傳送訊息,並在另一個微服務中接收訊息。

在此練習中,您會從 Catalog.API 專案將訊息傳送至佇列。 您將新增背景服務專案,以接收來自佇列的訊息,並將其傳送至主控台記錄以供顯示。

安裝先決條件

.NET Aspire 的必要條件如下:

  • .NET 8
  • Visual Studio 2022 Preview
  • Docker Desktop 或 Podman
  • Visual Studio 中的 .NET Aspire 工作負載

如果您已安裝這些套件,您可以直接跳到開始使用 RabbitMQ。

安裝 .NET 8

請遵循此 .NET 8 連結,然後為您的作業系統選取正確的安裝程式。 例如,如果您使用 Windows 11 和新式處理器,請選取適用於 Windows 的 x64 .NET 8 SDK。

下載完成之後,請執行安裝程式並遵循指示。 在終端視窗中,執行下列命令以確認安裝成功:

dotnet --version

您應該會看到您已安裝的 .NET SDK 版本號碼。 例如:

8.0.300-preview.24203.14

安裝 Visual Studio 2022 預覽版

請遵循此 Visual Studio 2022 預覽版連結,然後選取 [下載預覽版]。 下載完成之後,請執行安裝程式並遵循指示。

安裝 Docker Desktop

請遵循此 Docker Desktop 連結,然後為您的作業系統選取正確的安裝程式。 下載完成之後,請執行安裝程式並遵循指示。 為了獲得最佳效能和相容性,請使用 WSL 2 後端。

開啟 Docker 傳統型應用程式並接受服務合約。

安裝 Visual Studio 中的 .NET Aspire 工作負載

使用 .NET CLI 安裝 .NET Aspire 工作負載:

  1. 開啟終端機。

  2. 使用此指令更新 .NET 工作負載:

    dotnet workload update
    

    您應該會看到一則訊息,指出工作負載已成功更新。

    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. 使用此命令安裝 .NET Aspire 工作負載:

    dotnet workload install aspire
    

    您應該會看到一則訊息,指出已安裝 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. 使用此命令確認已安裝 .NET Aspire 工作負載:

    dotnet workload list
    

    您應該會看到 .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.
    

複製專案

讓我們使用 git 來取得尚未使用訊息代理程式的範例應用程式:

  1. 在命令列中,瀏覽至您選擇的資料夾,您可以在其中使用程式碼。

  2. 執行下列命令以複製範例應用程式:

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

建立 RabbitMQ 容器

讓我們從將 RabbitMQ 新增至應用程式主機專案開始。 當我們啟動方案時,.NET Aspire 會將 RabbitMQ 容器新增至應用程式,並將參考傳遞給使用該應用程式的專案:

  1. 啟動 Visual Studio,並選取 [開啟專案或方案]

  2. 瀏覽至您複製專案所在的資料夾。

  3. 按兩下 [開始] 資料夾,選取 [eShop.rabbitmq.sln] 方案,然後選取 [開啟]

  4. 在 [方案總管] 中,以滑鼠右鍵按一下 [eShop.AppHost] 專案並選取 [新增],然後選取 [.NET Aspire 套件]

  5. 在搜尋文字方塊中,於現有文字的結尾輸入 RabbitMQ

  6. 選取 [Aspire.Hosting.RabbitMQ] 套件。

  7. 在 [版本] 清單中,選取最新的 8.0.0 版本,然後選取 [安裝]

  8. 如果出現 [預覽變更] 對話方塊,請選取 [套用]

  9. 在 [接受授權] 對話方塊中,選取 [我接受]

  10. 在 [方案總管] 中,展開 [eShop.AppHost],然後按兩下 [Program.cs]

  11. 找出下列程式碼行:

    var builder = DistributedApplication.CreateBuilder(args);
    
  12. 緊接在該程式碼之後,若要註冊 RabbitMQ 伺服器,請新增下列程式碼:

    var messaging = builder.AddRabbitMQ("messaging");
    
  13. 找出下列程式碼,以註冊用於 .NET Aspire 協調流程的 Catalog.API 專案:

    var catalogApi = builder.AddProject<Catalog_API>("catalog-api")
        .WithReference(catalogDb);
    
  14. 若要將 RabbitMQ 服務傳遞至 Catalog.API 專案,請變更該程式碼以符合此程式碼:

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

將 RabbitMQ 新增至 Catalog.API 專案

現在,我們可以在 Catalog.API 專案中安裝和設定 RabbitMQ:

  1. 在 Visual Studio 的 [方案總管] 中,以滑鼠右鍵按一下 [Catalog.API] 專案、選取 [新增],然後選取 [.NET Aspire 套件]

  2. 在搜尋文字方塊中,於現有文字的結尾輸入 RabbitMQ

  3. 選取 [Aspire.RabbitMQ.Client] 套件。

  4. 在 [版本] 清單中,選取最新的 8.0.0 版本,然後選取 [安裝]

  5. 如果出現 [預覽變更] 對話方塊,請選取 [套用]

  6. 在 [接受授權] 對話方塊中,選取 [我接受]

  7. 在 [方案總管] 中,展開 [Catalog.API] 專案,然後按兩下 [Program.cs]

  8. Program.cs 檔案中,找出下列程式碼行:

    var builder = WebApplication.CreateBuilder(args);
    
  9. 緊接在該行之後,若要註冊 RabbitMQ 連線,請新增下列程式碼:

    builder.AddRabbitMQClient("messaging");
    

將訊息傳送至 RabbitMQ 佇列

當使用者要求目錄中的項目時,我們想要將訊息傳送至 RabbitMQ 佇列,以描述要求詳細資料。 讓我們立即新增該程式碼:

  1. 在 [方案總管] 中,展開 [Catalog.API] > [API],然後按兩下 [CatalogApi.cs]

  2. 找出下列程式碼,其會宣告 GetAllItems() 方法:

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services)
    {
    
  3. 若要使用相依性插入來取得 RabbitMQ 的連線,請修改程式碼以符合下列幾行:

    public static async Task<Results<Ok<PaginatedItems<CatalogItem>>, BadRequest<string>>> GetAllItems(
        [AsParameters] PaginationRequest paginationRequest,
        [AsParameters] CatalogServices services,
        RabbitMQ.Client.IConnection connection)
    {
    
  4. 找出下列程式碼行:

    var totalItems = await services.DbContext.CatalogItems
        .LongCountAsync();
    
  5. 緊接在該行之後,若要建立 RabbitMQ 傳訊通道,請新增下列程式碼:

    var channel = connection.CreateModel();
    
  6. 在下一行中,若要建立訊息佇列,請新增下列程式碼:

    channel.QueueDeclare(queue: "catalogEvents",
                         durable: false,
                         exclusive: false,
                         autoDelete: false,
                         arguments: null);
    
  7. 在下一行,若要傳送訊息,請新增下列程式碼:

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

新增訊息取用者專案

若要從 RabbitMQ 佇列接收訊息,讓我們建立新的專案:

  1. 在 [方案總管] 中,以滑鼠右鍵按一下方案,並指向 [加入],然後選取 [新增專案]

  2. 在 [搜尋範本] 文字方塊中,輸入主控台

  3. 選取 C# [主控台應用程式] 範本,然後選取 [下一步]

  4. 在 [專案名稱] 文字方塊中,輸入 RabbitConsumer,然後選取 [下一步]

  5. 在 [架構] 清單中,確定已選取 [.NET 8.0],然後選取 [建立]

  6. 在 [方案總管] 中,以滑鼠右鍵按一下 [AppHost] 專案,指向 [新增],然後選取 [專案參考]

  7. 在專案清單中,確定已選取 [RabbitConsumer],然後選取 [確定]

    顯示如何新增參考至參考 RabbitConsumer 專案的 AppHost 專案螢幕擷取畫面。

  8. 在 [方案總管] 中,展開 [AppHost],然後按兩下 [Program.cs]

  9. 尋找下列程式碼:

    builder.AddProject<WebApp>("webapp")
        .WithReference(catalogApi);
    
  10. 緊接在該程式碼之後,若要將 RabbitConsumer 專案新增至 .NET Aspire 協調流程,請新增下列程式碼:

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

設定訊息取用者專案

在我們可以在新的訊息取用者專案中接收訊息之前,我們必須將其設定為使用 AppHost 的 RabbitMQ 備份服務:

  1. 在 Visual Studio 的 [方案總管] 中,以滑鼠右鍵按一下 [RabbitConsumer] 專案、選取 [新增],然後選取 [.NET Aspire 套件]

  2. 在搜尋文字方塊中,於現有文字的結尾輸入 RabbitMQ

  3. 選取 [Aspire.RabbitMQ.Client] 套件。

  4. 在 [版本] 清單中,選取最新的 8.0.0 版本,然後選取 [安裝]

  5. 如果出現 [預覽變更] 對話方塊,請選取 [套用]

  6. 在 [接受授權] 對話方塊中,選取 [我接受]

  7. 在 [方案總管] 中,以滑鼠右鍵按一下 [RabbitConsumer] 專案,指向 [新增],然後選取 [專案參考]

  8. 在專案清單中,確定已選取 [eShop.ServiceDefaults],然後選取 [確定]

    顯示如何新增參考至參考 ServiceDefaults 專案的 RabbitConsumer 專案螢幕擷取畫面。

  9. 在 [方案總管] 中,展開 [RabbitConsumer] 專案,然後按兩下 [Program.cs]

  10. 移除所有預設程式碼,並將其取代為下列幾行:

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

    請注意,程式碼會使用 .NET Aspire 協調流程,將 RabbitMQ 服務新增至取用者專案。 您將使用該服務來擷取訊息。

接收 RabbitMQ 訊息

若要接收訊息,我們必須建立在背景中執行的整合,以等待訊息送達。 針對此工作使用類別 BackgroundService

  1. 在 [方案總管] 中,以滑鼠右鍵按一下 [RabbitConsumer] 專案,指向 [新增],然後選取 [類別]

  2. 在 [名稱] 文字方塊中,輸入 CatalogProcessingJob,然後選取 [新增]

  3. CatalogProcessingJob.cs 類別中,移除所有預設程式碼,並將其取代為下列幾行:

     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. 在 [方案總管]RabbitConsumer 專案中,按兩下 [Program.cs]

  5. 尋找下列程式碼:

    builder.AddRabbitMQClient("messaging");
    
  6. 緊接在該行之後,新增下列程式碼:

    builder.Services.AddHostedService<CatalogProcessingJob>();
    

測試解決方案

讓我們測試 RabbitMQ 備份服務及傳送和接收訊息的微服務:

  1. 在 Visual Studio 中,若要在偵錯模式中啟動應用程式,請按 F5,或選取 [偵錯] > [開始偵錯]

  2. 如果 [啟動 Docker 桌面] 訊息出現,請選取 [是]。 應用程式會在瀏覽器索引標籤中啟動並顯示 .NET Aspire 儀表板。

  3. 在 .NET Aspire 儀表板的 [資源] 清單中,請注意清單包含名稱為傳訊的新容器。 來源包含 rabbitmq:3。 此容器會執行 RabbitMQ 訊息代理程式。

    螢幕擷取畫面顯示 .NET Aspire 儀表板中顯示的 RabbitMQ 容器。

  4. 在左側導覽中,選取 [主控台]

  5. 在 [選取資源] 清單中,選取 [傳訊]。 此頁面會顯示 RabbitMQ 訊息代理程式的主控台記錄。 請注意,最後幾個訊息表示 RabbitMQ 已完成其啟動並接受一個連線。 此連線來自接收的 RabbitConsumer 專案。

  6. 在左側導覽中,選取 [資源]

  7. webapp 專案的行中,於 [端點] 資料行中,選取其中一個連結。 Northern Traders 首頁隨即開啟並顯示產品目錄。 此頁面會將訊息傳送至 RabbitMQ 佇列。

    顯示如何從 .NET Aspire 儀表板存取 WebApp 專案端點的螢幕擷取畫面。

  8. 切換回 .NET Aspire 儀表板。 在左側導覽中,選取 [主控台]

  9. 在 [選取資源] 清單中,選取 [傳訊]。 請注意,RabbitQ 已接受第二個連線。 此連線來自 Catalog.API 專案。

  10. 在 [選取資源] 清單中,選取 [取用者]。 此記錄適用於 RabbitConsumer 專案。 最後一個項目會顯示訊息「取得目錄中的所有項目。」此訊息已從 RabbitMQ 擷取並記錄。

    螢幕擷取畫面顯示從 RabbitMQ 佇列擷取的訊息,並顯示在取用者專案的主控台記錄中。