Dapr 與 .NET Aspire 結合使用獲得無與倫比的本地開發體驗

Dapr 提供了一組構建塊,用於抽象分佈式系統中常用的概念。這包括服務、緩存、工作流、復原能力、機密管理等之間的安全同步和異步通信。不必自己實現這些功能,可以消除樣板降低複雜性,並允許您專注於開發業務功能。

在您的時間有限並且您只想進行實驗的情況下,在Dapr初始設置上花費大量時間可能會令人沮喪。更不用說你尚未確定對本地開發體驗(故障排除、調試、載入等)的影響。也許你的一些同事最初會不情願,並認爲你正在讓他們的工作比現在更復雜。

本文將向你展示如何將 Dapr 與 .NET Aspire 結合使用,以獲得無與倫比的本地開發體驗。我們將創建一些 ASP.NET 核心和Node.js服務,這些服務將利用服務調用狀態管理和發佈/訂閱。好處是:

  • 通過編譯時常量、可測試代碼表示分佈式系統。
  • 集中式 OpenTelemetry Web 儀表板,用於瀏覽跟蹤、日誌和指標。
  • 一種將 Dapr sidecar 附加到應用程序的簡單方法。
  • 很少或沒有 YAML 配置文件。

使用 .NET Aspire for Dapr 將減少開發人員的入門時間。他們可以專注於使用 Dapr 進行功能開發,並花更少的時間設置本地環境。由於與 OpenTelemetry 的集成,可以更輕鬆地在本地對多個應用程序之間的交互進行故障排除,這通常是在部署代碼後在雲環境中才能獲得的。


具有 .NET Aspire 的 Dapr 分佈式系統示例

image

使用 .NET Aspire 進行 Dapr 實驗的目標是創建三個服務和 .NET Aspire 主機項目,後者充當業務流程協調程序:

  1. Alice,一個 ASP.NET 核心服務,它使用 Dapr 的服務調用從另一個服務檢索天氣數據,並使用狀態存儲對其進行緩存。
  2. Bob 是一個 ASP.NET Core 服務,它返回虛假的天氣數據,然後使用 pub/sub 發佈“請求天氣預報”事件。
  3. Carol,一個 Node.js Express Web 應用程序,訂閱“請求天氣預報”事件。

可在此 GitHub 存儲庫找到可以使用的完整代碼 .自述文件將指導您安裝必備組件並啓動服務。下面的代碼是 .NET Aspire 主機項目,我們在其中聲明這些服務、Dapr 組件及其關係,不涉及 YAML:

using Aspire.Hosting.Dapr;
using Microsoft.Extensions.Hosting;

var builder = DistributedApplication.CreateBuilder(args);

var stateStore = builder.AddDaprStateStore("statestore");
var pubSub = builder.AddDaprPubSub("pubsub");

builder.AddProject<Projects.AspireDaprDemo_AliceService>("alice")
     .WithDaprSidecar(new DaprSidecarOptions
     {
         // Loads the resiliency policy for service invocation from alice to bob
         ResourcesPaths = [Path.Combine("..", "resources")],
     })
     .WithReference(stateStore)
     .WithReference(pubSub);

builder.AddProject<Projects.AspireDaprDemo_BobService>("bob")
     .WithDaprSidecar()
     .WithReference(stateStore)
     .WithReference(pubSub);

builder.AddNpmApp("carol", Path.Combine("..", "AspireDaprDemo.CarolService"), "watch")
     .WithHttpEndpoint(port: 3000, env: "PORT")
     .WithEnvironment("NODE_TLS_REJECT_UNAUTHORIZED", builder.Environment.IsDevelopment() ? "0" : "1")
     .WithDaprSidecar()
     .WithReference(stateStore)
     .WithReference(pubSub);

builder.Build().Run();

啓動後,Aspire 會啓動所有服務,並在儀表板中提供分佈式系統的完整視圖

image

在此示例中,Alice 服務公開觸發上述交互的終結點。調用此終結點時,OpenTelemetry 跟蹤如下所示:/weatherforecast

image

加入開發團隊的開發人員可以快速瞭解分佈式系統的不同組件如何相互交互。在此屏幕截圖中,我們可以看到 flky Bob 服務返回錯誤,並且 Dapr 自動重試該操作。與 Dapr 提供的默認 Zipkin 實例相比,.NET Aspire 提供了一種更好的方法來可視化 OpenTelemetry 跟蹤,因爲跟蹤不僅在視覺上更清晰,而且儀表板還包括日誌和指標。

image

帶有 .NET Aspire 的 Dapr 無需配置且易於使用

通常,要配置 Dapr,您需要創建 YAML 配置文件來描述應用程序、sidecar 和網絡詳細信息(如 TCP 端口)。對於 .NET Aspire,這不是必需的。

Alice 和 Bob 之間的通信(他們的名字是在 Aspire 主機項目中聲明的)非常簡單,這要歸功於 Dapr SDK。

// Otherwise, get a fresh weather forecast from the flaky service "bob" and cache it
var forecasts = await client.InvokeMethodAsync<WeatherForecast[]>(HttpMethod.Get, "bob", "weatherforecast");

未在appsettings.json和環境變量中配置 URL。使用服務名稱bob是唯一必需的常量。Dapr 負責將請求路由到正確的服務。

狀態存儲和 pub/sub 也是如此。只有 Dapr sidecar 知道連接詳細信息,因此應用程序無需擔心它們。這避免了繁瑣的配置文件管理。想象一下,在分佈式系統中有 10 個服務,以及 4 個環境:本地環境、dev 環境、stg 環境和 prod。這可能表示要維護的 40 個潛在配置文件,以及數十個 URL 和連接字符串。多虧了 Dapr,您再也不用擔心這個問題了。

使用狀態存儲和 pub/sub 同樣簡單:

// Retrieve the weather forecast from the state store "statestore" declared in the Aspire host
var cachedForecasts = await client.GetStateAsync<CachedWeatherForecast>("statestore", "cache");

// [...]
// Save the weather forecast in the state store under the key "cache"
await client.SaveStateAsync("statestore", "cache", new CachedWeatherForecast(forecasts, DateTimeOffset.UtcNow));

// Publish an event "WeatherForecastMessage" to the pub/sub "pubsub" declared in the Aspire host, with the topic "weather"
await client.PublishEventAsync("pubsub", "weather", new WeatherForecastMessage("Weather forecast requested!"));


這是訂閱“天氣”主題的 Carol 服務的片段。請記住,.NET Aspire 和 Dapr 都與語言無關:

// Events are received through HTTP POST requests (push delivery model)
app.post("/subscriptions/weather", (req, res) => {
   console.log("Weather forecast message received:", req.body.data);
   res.sendStatus(200);
});

.NET Aspire 如何與 Dapr 配合使用?

.NET Aspire 在資源上使用WithDaprSidecardapr,該方法指示 啓動可執行文件的實例。

// [...]
     .WithDaprSidecar()
     .WithReference(stateStore)
     .WithReference(pubSub);

Dapr傳遞的參數取決於服務引用的組件數以及在調用上述方法期間可能傳遞的選項。

這裏要記住兩個關鍵點:

  • .NET Aspire 中內置組件(如狀態存儲和 pub/sub)的 YAML 代碼在臨時文件夾中自動生成。
  • 默認情況下,會分配隨機端口,因此您不必記住它們或擔心可能的衝突。

如果您想了解詳細信息,可以在 .NET Aspire 源代碼中的 DaprDistributedApplicationLifecycleHook 類中看它是如何實現的。隨後,編排的應用程序被傳遞環境變量,允許 Dapr SDK 與 sidecar 進行通信。這可以從 Aspire 儀表板上的資源詳細信息中看出:

image

處理更復雜的 Dapr 場景

在此實驗中,我們使用了 .NET Aspire 本機支持的兩個 Dapr 組件。但是,可以使用以下方法AddDaprComponent 聲明其他類型的組件:

var stateStore = builder.AddDaprStateStore("statestore");
var pubSub = builder.AddDaprPubSub("pubsub");

還可以聲明資源,例如彈性策略,並將它們分配給 sidecar:

builder.AddProject<Projects.AspireDaprDemo_AliceService>("alice")
     .WithDaprSidecar(new DaprSidecarOptions
     {
         // Loads the resiliency policy for service invocation from alice to bob
         ResourcesPaths = [Path.Combine("..", "resources")],
     })
     .WithReference(stateStore)
     .WithReference(pubSub);

builder.AddProject<Projects.AspireDaprDemo_BobService>("bob")
     .WithDaprSidecar()
     .WithReference(stateStore)
     .WithReference(pubSub);

builder.AddNpmApp("carol", Path.Combine("..", "AspireDaprDemo.CarolService"), "watch")
     .WithHttpEndpoint(port: 3000, env: "PORT")
     .WithEnvironment("NODE_TLS_REJECT_UNAUTHORIZED", builder.Environment.IsDevelopment() ? "0" : "1")
     .WithDaprSidecar()
     .WithReference(stateStore)
     .WithReference(pubSub);


相關鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章