當前位置: 妍妍網 > 碼農

.NET Aspire 應用程式剖析

2024-07-07碼農


添加元件很容易,因為 Aspire 具有成熟的編排器功能,例如服務發現。啟動和偵錯應用程式也很容易。您所要做的就是啟動 Aspire 主機應用程式,就像啟動和偵錯任何標準 .NET 計畫一樣。單擊 IDE 中的 「Run」( 執行 )按鈕或從 CLI 執行命令將啟動 .NET Aspire 主機及其編排的所有應用程式。您可以在其中任何一個中放置斷點,它們將被命中。dotnet run

今天,我們將研究基於 .NET Aspire 啟動計畫樣版的基本 .NET Aspire 應用程式。

Aspire 入門

如果以前未使用過 .NET Aspire,則可以按照 Microsoft 提供的官方文件中的說明建立第一個應用程式。假設我們基於 Aspire Starter Project 樣版建立了一個新計畫,並將其命名為 AspireApp 。這就是我們最終會得到的:

我們可以在此處找到我們將要介紹的計畫的完整範例。

此設定包括以下應用程式:

  • AspireApp.Web,這是一個 Blazor Web 應用程式,其使用者介面可從外部 REST API 終結點拉取數據。

  • AspireApp.ApiService,這是 Blazor 應用程式從中提取數據的 REST API 應用程式。

  • AspireApp.AppHost,這是協調其他兩個應用程式的 Aspire 業務流程協調程式。

  • 還有一個名為的類別庫,它為 .NET Aspire 編排的應用程式提供一些共享功能。AspireApp.ServiceDefaults

    接下來,讓我們看一下編排是如何發生的。

    使用 .NET Aspire 進行編排

    如果我們啟動 playground 並等待應用程式構建,我們將能夠看到如下所示的儀表板:

    此儀表板向我們展示了作為編排分布式應用程式的一部份正在執行哪些服務。儀表板包含每個服務的以下資訊:

  • 服務型別

  • 在 Aspire 環境上下文中使用的唯一名稱

  • 狀態,告訴我們服務是否正在執行

  • Source,它指向表示服務的計畫

  • 服務終結點(如果服務有一個)The service endpoint (if the service has one)

  • 服務日誌

  • 服務詳情

  • 我們知道上述應用程式正在執行。首先,這是儀表板上列下的值告訴我們的。其次,如果我們透過單擊**「控制台**」索引標籤開啟任一應用程式的日誌,我們應該期望它看起來像這樣:State

    如果我們返回到**「資源**」索引標籤,我們將能夠單擊任何應用程式的終結點 URL,它將帶我們到與終結點關聯的地址。因此,讓我們單擊 webfrontend 的端點:

    這應該會開啟一個 Blazor UI 應用程式,我們可以在其中導航到該索引標籤。此索引標籤包含 Blazor 應用程式從 API 檢索的數據。它應該看起來與此類似(盡管確切的值可能會有所不同):Weather

    因此,這就是我們如何讓 UI 和 API 協同工作。Aspire 允許我們檢視這兩個應用程式並導航到它們相應的地址。但遠不止於此。在深入研究其計畫結構之前,讓我們快速總結一下 Aspire 的好處。

    .NET Aspire 的優點

    沒有什麽能阻止我們在沒有任何編排器的情況下讓 UI 應用程式與 API 應用程式進行通訊。但是,業務流程協調程式(如 NET Aspire)使此過程變得更加容易。以下是它的一些好處:

    服務發現

    如果我們想讓 UI 應用程式與 API 通訊,我們需要知道 API 的地址。但是,如果我們在負載均衡器或反向代理後面執行 API,該怎麽辦?如果 API 應用程式部署到完全不同的伺服器怎麽辦?

    在這些情況下,應用程式的地址將發生變化。如果沒有編排器,就很難跟蹤它。.NET Aspire 解決了這個問題,我們很快就會看到。

    .NET Aspire 業務流程協調程式保留應用程式的實際地址。應用程式本身不需要知道此資訊。它們可以簡單地透過唯一的服務名稱參照其他應用程式。Aspire 主機將進行地址解析,並根據服務名稱提供正確的網路地址。

    因此,在這種情況下,API 應用程式的地址是否更改並不重要。Blazor UI 應用程式仍能夠連線到正確的終結點。

    自動健康檢查

    正如我們在儀表板上看到的,兩個服務的狀態都顯示為**「正在執行**」。此狀態可用,因為 .NET Aspire 具有一種自動評估服務執行狀況的方法。此功能使我們能夠檢視我們的服務是否有任何問題,並立即采取適當的措施。

    此外,自動執行狀況檢查允許業務流程協調程式嘗試修復失敗的應用程式,而無需任何外部參與。這是通常首先發生的事情。

    同時監控所有元件

    但也許 Aspire 的最大好處是能夠以方便和使用者友好的方式在一個地方監控我們的整個分布式應用程式。

    我們可以檢視每個服務的即時狀態。我們可以檢視所有日誌。我們可以檢視跟蹤和指標。所有這一切都是透過透過直觀的選單導航並透過人類可讀的名稱選擇正確的服務來完成的。

    在開發電腦上執行分布式套用

    分布式應用程式傳統上因難以在本地開發機器上執行而臭名昭著。開發人員要麽不得不花費數小時來配置他們的環境,要麽只測試分布式應用程式的某些元件,同時模擬或模擬所有其他元件。

    .NET Aspire 使生成和偵錯整個分布式應用程式變得容易,即使它們非常復雜。我們需要做的就是向 Aspire 主機註冊所有服務,其余的由編排器完成。

    接下來,讓我們深入了解 .NET Aspir 的內部情況,了解它是如何進行業務流程的。

    設定 .NET Aspire Orchestrator

    .NET Aspire 是一個復雜的系統,有很多東西需要解壓縮。我們將從基礎開始。首先,我們將介紹使 .NET Aspire 工作的基本依賴關系。然後,我們將繼續透過業務流程協調程式註冊應用程式。

    安裝 .NET Aspire 依賴項

    Aspire 應用程式需要一個主機應用程式,該應用程式充當業務流程協調程式。在上面的 Playground 中,計畫扮演了這個角色。AspireApp.AppHost

    Aspire 主機計畫需要 NuGet 包。如果我們開啟檔,我們會發現這個包在第 17 行 被參照。Aspire.Hosting.AppHostAspireApp.AppHost.csproj

    主機應用程式還需要參照它要編排的所有應用程式。在我們的例子中,有兩個:

  • AspireApp.Web,這是一個 Blazor Web 應用程式,其使用者介面可從外部 REST API 終結點拉取數據。

  • AspireApp.ApiService,這是 Blazor 應用程式從中提取數據的 REST API 應用程式。

  • 一旦我們有了所有依賴項,我們就可以在主機應用程式的啟動程式碼中促進業務流程。

    主機應用程式啟動

    與任何 .NET 應用程式一樣,可以在類中找到應用程式的啟動程式碼。我們首先執行以下程式碼來建立主機生成器:AspireApp.AppHostProgram.cs

    var builder = DistributedApplication.CreateBuilder(args);

    與標準 ASP.NET Core 套用一樣,我們首先例項化主機構建器。但是,這是 .NET Aspire 使用的特殊主機生成器。它來自專門用於構建主機應用程式的類。DistributedApplication

    然後,我們可以使用以下程式碼來執行此操作:

    var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

    這就是我們註冊 API 應用程式的方式。物件 方法,它帶有尖括弧中的泛型型別規範,即 .這是一個自動生成的型別,其名稱是這樣推斷的:builderAddProject()<Projects.AspireApp_ApiService>

  • 該部件指示它是解決方案中的計畫之一。Project

  • 從計畫名稱推斷出部件。這些點將替換為底線,以確保它由單一型別表示。AspireApp_ApiServiceAspireApp.ApiService

  • 因此,這種型別在我們的任何計畫中都不存在。這種型別是自動生成的,並從我們的一個計畫的名稱中推斷出來。此型別將包含將所述計畫註冊為主機可以編排的應用程式所需的所有程式碼。

    該參數是我們註冊服務時所使用的名稱。在本例中,我們給它起的名字是 .apiservice

    註冊 UI 應用程式 #

    註冊 API 後,我們就可以註冊 UI。在我們的範例計畫中,這是如何完成的:

    builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(apiService);

    最初,我們執行的操作與註冊 API 服務時相同。我們使用從計畫推斷出的型別參照來呼叫該方法。我們給這個計畫起了個名字。AddProjectAspireApp.Webwebfrontend

    但是,我們在這裏還做了另一件事。我們正在呼叫該方法,並將先前註冊的 API 服務參照插入其中。這樣做是為了讓 Blazor UI 應用程式可以透過服務發現參照 API 應用程式。WithReference()

    如果我們再次檢視儀表板,我們將看到其上顯示的服務的名稱為 webfrontend apiservice 。這些名稱是任意的,但它們是我們在 Aspire 業務流程協調程式的啟動程式碼中註冊服務時使用的名稱。

    伺服器預設值簡介

    .NET 上下文中的服務預設值 Aspire 是允許將套用添加到 Aspire 業務流程協調程式的擴充套件方法的集合。這些擴充套件方法作為 .NET Aspire 計畫樣版中包含的類別庫提供。

    這些擴充套件方法需要用於以下目的:

  • 啟用服務發現

  • 使業務流程協調程式能夠評估應用程式的執行狀況

  • 從應用程式收集指標

  • 編排套用共享的其他常見功能

  • 這些擴充套件方法作為解決方案中的類別庫出現的原因是,可以修改它們以適應特定的業務方案。例如,開發人員可能希望選擇與預設指標庫不同的指標庫。或者他們可能想要添加新功能。

    在我們的設定中,伺服器預設值由計畫表示。由於此計畫是一個類別庫,其目的是為 ASP.NET Core 應用程式的啟動程式碼添加擴充套件方法,因此此計畫需要參照框架包。AspireApp.ServiceDefaultsMicrosoft.AspNetCore.App

    此包允許庫存取 ASP.NET Core 使用的型別,例如 和 。IHostApplicationBuilderWebApplication

    我們還需要添加對其他包的參照,這些包支持我們正在尋找的特定功能,例如服務發現和遙測。

    添加擴充套件方法

    擴充套件方法可以在計畫的檔中找到。這是它的內容:

    usingMicrosoft.AspNetCore.Builder;
    usingMicrosoft.AspNetCore.Diagnostics.HealthChecks;
    usingMicrosoft.Extensions.DependencyInjection;
    usingMicrosoft.Extensions.Diagnostics.HealthChecks;
    usingMicrosoft.Extensions.Logging;
    usingOpenTelemetry;
    usingOpenTelemetry.Metrics;
    usingOpenTelemetry.Trace;
    namespaceMicrosoft.Extensions.Hosting;
    // Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
    // This project should be referenced by each service project in your solution.
    // To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
    publicstatic classExtensions
    {
    publicstaticIHostApplicationBuilderAddServiceDefaults(thisIHostApplicationBuilder builder)
    {
    builder.ConfigureOpenTelemetry();
    builder.AddDefaultHealthChecks();
    builder.Services.AddServiceDiscovery();
    builder.Services.ConfigureHttpClientDefaults(http =>
    {
    // Turn on resilience by default
    http.AddStandardResilienceHandler();
    // Turn on service discovery by default
    http.AddServiceDiscovery();
    });
    return builder;
    }
    publicstaticIHostApplicationBuilderConfigureOpenTelemetry(thisIHostApplicationBuilder builder)
    {
    builder.Logging.AddOpenTelemetry(logging =>
    {
    logging.IncludeFormattedMessage = true;
    logging.IncludeScopes = true;
    });
    builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics =>
    {
    metrics.AddAspNetCoreInstrumentation()
    .AddHttpClientInstrumentation()
    .AddRuntimeInstrumentation();
    })
    .WithTracing(tracing =>
    {
    tracing.AddAspNetCoreInstrumentation()
    // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
    //.AddGrpcClientInstrumentation()
    .AddHttpClientInstrumentation();
    });
    builder.AddOpenTelemetryExporters();
    return builder;
    }
    privatestaticIHostApplicationBuilderAddOpenTelemetryExporters(thisIHostApplicationBuilder builder)
    {
    var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
    if (useOtlpExporter)
    {
    builder.Services.AddOpenTelemetry().UseOtlpExporter();
    }
    // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
    //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
    //{
    // builder.Services.AddOpenTelemetry()
    // .UseAzureMonitor();
    //}
    return builder;
    }
    publicstaticIHostApplicationBuilderAddDefaultHealthChecks(thisIHostApplicationBuilder builder)
    {
    builder.Services.AddHealthChecks()
    // Add a default liveness check to ensure app is responsive
    .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
    return builder;
    }
    publicstaticWebApplicationMapDefaultEndpoints(thisWebApplication app)
    {
    // Adding health checks endpoints to applications in non-development environments has security implications.
    // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
    if (app.Environment.IsDevelopment())
    {
    // All health checks must pass for app to be considered ready to accept traffic after starting
    app.MapHealthChecks("/health");
    // Only health checks tagged with the "live" tag must pass for app to be considered alive
    app.MapHealthChecks("/alive", newHealthCheckOptions
    {
    Predicate = r => r.Tags.Contains("live")
    });
    }
    return app;
    }
    }

    在此檔中,我們結合了這兩種擴充套件方法和型別,這兩種方法都用於 ASP.NET Core 應用程式的啟動程式碼中。IHostApplicationBuilderWebApplication

    用於註冊應用程式可以使用的服務。該型別用於向應用程式添加 HTTP 終結點,以及向請求處理管道添加步驟。IHostApplicationBuilderWebApplication

    我們將在本章的相關課程中詳細介紹這些方法中的每一種。但是,以下是每種方法的用途的快速摘要:

  • 第 34 行 的方法用於註冊可以在應用程式內收集指標的服務。ConfigureOpenTelemetry()

  • 第 68 行 的方法配置了將指標匯出應用程式的功能,以便它們可用於監視應用程式。AddOpenTelemetryExporters()

  • 第 14 行 的方法呼叫這兩個方法,並執行一些額外的依賴項註冊,例如添加服務發現所需的服務。AddServiceDefaults()

  • 第 102 行 的方法將執行狀況檢查終結點添加到應用程式。MapDefaultEndpoints()

  • 一旦我們有了這些方法,我們將需要從相關應用程式的啟動程式碼中呼叫它們。

    使用擴充套件方法

    如果我們在計畫中開啟檔,我們將能夠找到以下行:Program.csAspireApp.Web

    builder.AddServiceDefaults();

    這呼叫了我們之前檢視的擴充套件方法。這就是我們註冊與 .NET Aspire 關聯的所有依賴項的方式。這允許此應用程式可由 Aspire 業務流程協調程式管理。

    我們還在檔下方進行了以下呼叫:

    app.MapDefaultEndpoints();

    這又是我們在服務預設值中添加的擴充套件方法之一。

    如果我們在計畫中開啟檔,我們會發現正在呼叫相同的擴充套件方法。Program.csAspireApp.ApiService

    .NET Aspire 中的服務發現

    服務發現是分布式系統和微服務架構的一個關鍵方面。它是指在網路環境中自動檢測和註冊可用服務的過程。在微服務體系結構中,應用程式由許多透過網路相互通訊的小型獨立服務組成,服務發現使這些服務能夠動態定位並相互通訊,而無需手動配置。

    服務發現涉及幾個關鍵元件:

  • 服務註冊 :當微服務啟動時,它會向服務註冊中心或發現服務註冊。此註冊通常包括服務的網路位置(例如 IP 地址和埠)、後設資料以及可能的執行狀況等資訊。

  • 服務查詢 :需要與特定服務互動的其他微服務或客戶端可以查詢服務註冊中心,以發現其位置和其他相關詳細資訊。此查詢可以在執行時動態執行,使服務能夠適應網路拓撲的變化或服務的添加/刪除。

  • 動態更新 :服務發現系統支持對登錄檔的動態更新,允許服務加入或離開網路而不會造成中斷。這可確保登錄檔始終反映系統的當前狀態。

  • 負載均衡 :服務發現通常與負載均衡機制整合,以在服務的多個例項之間分配傳入請求。這透過均勻分配工作負載來提高系統的可伸縮性、容錯性和效能。

  • 註冊服務發現元件

    在使用 .NET Aspire 啟用服務發現之前,我們需要在要添加到業務流程協調程式的應用程式中安裝 NuGet 包。我們在計畫中就是這樣做的。Microsoft.Extensions.ServiceDiscoveryAspireApp.ServiceDefaults

    啟用服務發現

    接下來,我們需要啟用服務發現,以便應用程式可以使用它。在我們的範例中,這是在類別庫檔的方法中完成的。AddServiceDefaults()Extensions.csAspireApp.ServiceDefaults

    下面是此方法中的特定呼叫,用於註冊服務發現所需的所有依賴項:

  • builder.Services.AddServiceDiscovery();

  • http.AddServiceDiscovery();

  • 一旦我們註冊了所有必需的元件,就可以開始使用服務發現了。

    使用服務發現

    如果我們開啟計畫資料夾下的檔,我們將找到一個服務發現用法的範例。Program.csAspireApp.Web

    首先,我們需要確保註冊所有相關元件,這是透過呼叫擴充套件方法完成的。然後,在我們建立用於連線到 API 應用程式的 HTTP 客戶端的塊中,我們有以下內容:AddServiceDefaults()

    client.BaseAddress = new("https+http://apiservice");

    通常,我們會使用標準 URL 作為基址,但這次不是。相反,我們將 HTTP 客戶端指向我們想要獲取其地址的服務的名稱。該名稱是我們在 .NET Aspire 業務流程協調程式中註冊此服務的名稱。

    在此範例中,我們將協定定義為 。這意味著我們將嘗試透過HTTPS連線到服務,但如果我們不能,我們將使用HTTP。但是,首選 HTTPS。https+http

    然後我們有一個標準冒號,後跟一個雙斜杠,我們在任何 URL 中使用它。最後,我們有了要連線的服務的名稱,即 apiservice

    在此設定中,註冊為 apiservice 的應用程式可以移動到其他伺服器。其地址可能會更改。它的埠可能會改變。但對於我們的客戶應用程式來說,這些都無關緊要,因為它不知道它的地址,也不關心它。Aspire 主機應用程式將解析要連線到的正確地址。

    結束語

    正如我們所看到的,Aspire 受到 .NET 社群的喜愛絕非偶然。與其他編排器相比,它使在本地構建分布式應用程式的過程變得毫不費力。

    如果你喜歡我的文章,請給我一個贊!謝謝