mcpField
D
dotnet-aspire-patterns

dotnet-aspire-patterns

github.com/wshaddixクラウド・DevOps8667 回インストール35 週間前に更新
リポジトリ

dotnet-aspire-patterns について

dotnet-aspire-patterns は、分散アプリケーションを開発する人向けの .NET Aspire スキルです。AppHostによるオーケストレーション、サービスディスカバリー、バックエンドサービス用コンポーネント、ローカルの可観測性、ヘルスチェックを扱い、開発時の実行管理と本番デプロイを区別します。

主な機能

  1. 01AppHostのトポロジーとリソースのライフサイクル
  2. 02サービスディスカバリーと接続文字列
  3. 03データベース、キャッシュ、メッセージブローカー用コンポーネント
  4. 04ヘルスチェックとテレメトリーのServiceDefaults
  5. 05ログ、トレース、メトリクスを表示するローカルダッシュボード
  6. 06Aspireと手動オーケストレーションの選択指針

活用シーン

  1. 01複数の.NETサービスとバックエンド基盤の接続
  2. 02リソースのヘルス状態に応じた起動順序の設定
  3. 03サービスプロジェクト間での可観測性の標準化
  4. 04ローカルオーケストレーション方式の検討

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-aspire-patterns

インストール後、Claude Code で/dotnet-aspire-patternsを入力して読み込まれたか確認します。

詳細

dotnet-aspire-patterns

クラウド対応の分散アプリケーションを構築するための .NET Aspire オーケストレーションパターンです。AppHost の構成、サービスディスカバリー、バックエンドサービス(データベース、キャッシュ、メッセージブローカー)を統合するためのコンポーネントモデル、ローカルでの可観測性を実現する Aspire ダッシュボード、分散ヘルスチェック、Aspire と手動のコンテナーオーケストレーションのどちらを選ぶべきかについて説明します。

対象外: Dockerfile の記述とマルチステージビルドについては、[skill:dotnet-containers] を参照してください。Kubernetes マニフェスト、Helm チャート、Docker Compose については、[skill:dotnet-container-deployment] を参照してください。OpenTelemetry SDK の構成とカスタムメトリクスについては、[skill:dotnet-observability] を参照してください。DI サービスのライフタイムの仕組みについては、[skill:dotnet-csharp-dependency-injection] を参照してください。バックグラウンドサービスのホスティングについては、[skill:dotnet-background-services] を参照してください。

相互参照:[skill:dotnet-containers] ではコンテナーイメージの最適化とベースイメージの選択、[skill:dotnet-container-deployment] では Kubernetes/Compose を使った本番環境へのデプロイ、[skill:dotnet-observability] では Aspire の既定値を超える OpenTelemetry の詳細、[skill:dotnet-csharp-dependency-injection] では DI の基礎、[skill:dotnet-background-services] ではホステッドサービスのライフサイクルパターンを説明しています。


Aspire の概要

.NET Aspire は、可観測性を備えた本番環境対応の分散アプリケーションを構築するための、明確な方針を持つスタックです。次の機能を提供します。

  • オーケストレーション -- 分散トポロジーを C#(AppHost)で定義します
  • コンポーネント -- 一般的なバックエンドサービス向けに事前構成された NuGet パッケージ
  • サービスの既定値 -- OpenTelemetry、ヘルスチェック、レジリエンスの共有構成
  • ダッシュボード -- トレース、ログ、メトリクス、リソースの状態を確認できるローカル開発用 UI

Aspire はデプロイ先ではありません。ローカルでの開発およびテスト体験をオーケストレーションします。本番環境向けには、デプロイツール(Azure Developer CLI、Kubernetes など)が使用するマニフェストを生成します。

Aspire を使用する場面
シナリオ推奨事項
複数の .NET サービスとバックエンドインフラストラクチャAspire AppHost -- ローカル開発とサービスの接続を簡素化します
データベースを備えた単一の API任意 -- トポロジーがシンプルな場合、Aspire の導入によってオーバーヘッドが増える可能性があります
.NET 以外のサービスのみ(Node、Python)Aspire からコンテナーイメージを参照できますが、ツールの利点は小さくなります
ローカル開発で Kubernetes/Compose をすでに使用している移行コストを評価してください。Aspire は開発シナリオで docker-compose を置き換えます
チームで一貫した可観測性の既定値が必要Aspire ServiceDefaults によって、すべてのプロジェクトの OTel を標準化できます

AppHost の構成

AppHost は、分散アプリケーションのトポロジーを定義する .NET プロジェクト(Aspire.Hosting.AppHost SDK)です。他のプロジェクトやバックエンドサービスを参照し、サービスディスカバリーによってそれらを接続します。

AppHost プロジェクトのセットアップ
<Project Sdk="Microsoft.NET.Sdk">

  
  <Sdk Name="Aspire.AppHost.Sdk" Version="9.1.*" />

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <IsAspireHost>true</IsAspireHost>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.AppHost" Version="9.1.*" />
    <PackageReference Include="Aspire.Hosting.PostgreSQL" Version="9.1.*" />
    <PackageReference Include="Aspire.Hosting.Redis" Version="9.1.*" />
    <PackageReference Include="Aspire.Hosting.RabbitMQ" Version="9.1.*" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\MyApi\MyApi.csproj" />
    <ProjectReference Include="..\MyWorker\MyWorker.csproj" />
  </ItemGroup>

</Project>
トポロジーの定義
var builder = DistributedApplication.CreateBuilder(args);

// Backing services -- Aspire manages containers automatically
var postgres = builder.AddPostgres("pg")
    .WithPgAdmin()              // Adds pgAdmin UI container
    .AddDatabase("ordersdb");

var redis = builder.AddRedis("cache")
    .WithRedisCommander();      // Adds Redis Commander UI

var rabbitmq = builder.AddRabbitMQ("messaging")
    .WithManagementPlugin();    // Adds RabbitMQ management UI

// Application projects -- wired with service discovery
var api = builder.AddProject<Projects.MyApi>("api")
    .WithReference(postgres)
    .WithReference(redis)
    .WithReference(rabbitmq)
    .WithExternalHttpEndpoints();  // Marks endpoints as public in deployment manifests

builder.AddProject<Projects.MyWorker>("worker")
    .WithReference(postgres)
    .WithReference(rabbitmq)
    .WaitFor(api);              // Start worker after API is healthy

builder.Build().Run();
リソースのライフサイクル

WaitFor は起動順序を制御します。依存関係から正常であることが報告されるまで、リソースは起動を待機します。

// Worker waits for both the database and API to be ready
builder.AddProject<Projects.MyWorker>("worker")
    .WithReference(postgres)
    .WaitFor(postgres)          // Wait for database container health check
    .WaitFor(api);              // Wait for API health endpoint

WaitFor がない場合、リソースは並行して起動します。起動順序が重要な場合(たとえば、データベーススキーマが存在している必要があるワーカー)にのみ使用してください。


サービスディスカバリー

Aspire はサービスディスカバリーを自動的に構成し、ハードコードされた URL ではなくリソース名でプロジェクト同士を解決できるようにします。

仕組み
  1. AppHost は、エンドポイント情報を環境変数と構成として注入します
  2. Aspire.ServiceDefaults プロジェクトが Microsoft.Extensions.ServiceDiscovery を構成します
  3. アプリケーションコードは、HttpClient または接続文字列を介してサービス名でサービスを解決します
検出されたサービスの使用
// In MyApi/Program.cs
var builder = WebApplication.CreateBuilder(args);

// AddServiceDefaults registers service discovery, OpenTelemetry, health checks
builder.AddServiceDefaults();

// HttpClient resolves "worker" via service discovery
builder.Services.AddHttpClient("worker-client", client =>
{
    client.BaseAddress = new Uri("https+http://worker");
});

https+http:// スキームプレフィックスは、サービスディスカバリープロバイダーに HTTPS を優先して試し、失敗した場合は HTTP にフォールバックするよう指示します。これは、Aspire でサービス間通信を行う際に推奨されるパターンです。

接続文字列

データベースやキャッシュなどのバックエンドサービスでは、Aspire は標準の ConnectionStrings 構成セクションを介して接続文字列を注入します。

// AppHost: .WithReference(postgres) on the API project
// injects ConnectionStrings__ordersdb automatically

// In MyApi/Program.cs
builder.AddNpgsqlDbContext<OrdersDbContext>("ordersdb");
// Resolves ConnectionStrings:ordersdb from configuration

コンポーネントモデル

Aspire コンポーネントは、バックエンドサービス向けに事前構成されたクライアント統合を提供する NuGet パッケージです。接続管理、ヘルスチェック、テレメトリ、回復性を処理します。

ホスティングパッケージとクライアントパッケージ
パッケージの種類インストール先目的
Aspire.Hosting.*AppHost プロジェクトリソース(コンテナー、接続)を定義して構成する
Aspire.* (client)サービスプロジェクトヘルスチェックとテレメトリを使用してリソースを利用する

<PackageReference Include="Aspire.Hosting.PostgreSQL" Version="9.1.*" />


<PackageReference Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.1.*" />
一般的なコンポーネント
コンポーネントホスティングパッケージクライアントパッケージ
PostgreSQL(EF Core)Aspire.Hosting.PostgreSQLAspire.Npgsql.EntityFrameworkCore.PostgreSQL
PostgreSQL(Npgsql)Aspire.Hosting.PostgreSQLAspire.Npgsql
Redis(キャッシュ)Aspire.Hosting.RedisAspire.StackExchange.Redis
Redis(出力キャッシュ)Aspire.Hosting.RedisAspire.StackExchange.Redis.OutputCaching
RabbitMQAspire.Hosting.RabbitMQAspire.RabbitMQ.Client
Azure Service BusAspire.Hosting.Azure.ServiceBusAspire.Azure.Messaging.ServiceBus
SQL Server(EF Core)Aspire.Hosting.SqlServerAspire.Microsoft.EntityFrameworkCore.SqlServer
MongoDBAspire.Hosting.MongoDBAspire.MongoDB.Driver
クライアントの登録
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();

// Each Add* method registers the client, health check, and telemetry
builder.AddNpgsqlDbContext<OrdersDbContext>("ordersdb");
builder.AddRedisClient("cache");
builder.AddRabbitMQClient("messaging");

コンポーネントの Add* メソッドは、次の処理を行います。

  1. DI にクライアント/DbContext を登録する
  2. リソースのヘルスチェックを追加する
  3. クライアントの OpenTelemetry インストルメンテーションを構成する
  4. 既定の回復性設定(再試行、タイムアウト)を適用する

サービスの既定値

ServiceDefaults プロジェクトは、すべてのサービスプロジェクトから参照される共有ライブラリです。横断的な関心事を標準化します。

ServiceDefaults が構成する内容
public static class Extensions
{
    public static IHostApplicationBuilder AddServiceDefaults(
        this IHostApplicationBuilder builder)
    {
        // Service discovery
        builder.ConfigureOpenTelemetry();
        builder.AddDefaultHealthChecks();
        builder.Services.AddServiceDiscovery();

        // Resilience for HttpClient
        builder.Services.ConfigureHttpClientDefaults(http =>
        {
            http.AddStandardResilienceHandler();
            http.AddServiceDiscovery();
        });

        return builder;
    }

    public static IHostApplicationBuilder ConfigureOpenTelemetry(
        this IHostApplicationBuilder builder)
    {
        builder.Logging.AddOpenTelemetry(logging =>
        {
            logging.IncludeFormattedMessage = true;
            logging.IncludeScopes = true;
        });

        builder.Services.AddOpenTelemetry()
            .WithMetrics(metrics => metrics
                .AddAspNetCoreInstrumentation()
                .AddHttpClientInstrumentation()
                .AddRuntimeInstrumentation())
            .WithTracing(tracing => tracing
                .AddAspNetCoreInstrumentation()
                .AddGrpcClientInstrumentation()
                .AddHttpClientInstrumentation());

        builder.AddOpenTelemetryExporters();
        return builder;
    }

    public static IHostApplicationBuilder AddDefaultHealthChecks(
        this IHostApplicationBuilder builder)
    {
        builder.Services.AddHealthChecks()
            .AddCheck("self", () => HealthCheckResult.Healthy());

        return builder;
    }

    public static WebApplication MapDefaultEndpoints(
        this WebApplication app)
    {
        app.MapHealthChecks("/health");
        app.MapHealthChecks("/alive", new HealthCheckOptions
        {
            Predicate = r => r.Tags.Contains("live")
        });

        return app;
    }
}
ServiceDefaults の使用

すべてのサービスプロジェクトで ServiceDefaults プロジェクトを参照し、拡張メソッドを呼び出します。

var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();

// ... service-specific registrations

var app = builder.Build();
app.MapDefaultEndpoints();

// ... middleware and endpoints

app.Run();

ダッシュボード

Aspire ダッシュボードは、AppHost とともに自動的に起動するローカルの可観測性 UI です。次の項目が表示されます。

  • リソース -- すべてのプロジェクト、コンテナー、実行可能ファイルの状態
  • コンソールログ -- すべてのリソースから集約された stdout/stderr
  • 構造化ログ -- 構造化プロパティを含む OpenTelemetry ログレコード
  • トレース -- すべてのサービスにまたがる分散トレース
  • メトリクス -- リアルタイムのメトリクスチャート
ダッシュボードへのアクセス

AppHost(dotnet run --project MyApp.AppHost)を実行すると、ダッシュボードの URL がコンソールに表示されます。

info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17043/login?t=<token>
Aspire を使用しないプロジェクトでのダッシュボード

Aspire スタック全体を使用しないプロジェクト向けに、ダッシュボードをスタンドアロンコンテナーとして利用できます。

docker run --rm -it -p 18888:18888 -p 4317:18889 \
  -d --name aspire-dashboard \
  mcr.microsoft.com/dotnet/aspire-dashboard:9.1

アプリを構成して OTLP テレメトリを http://localhost:4317 にエクスポートし、http://localhost:18888 で表示します。


ヘルスチェックと分散トレーシング

コンポーネントのヘルスチェック

各 Aspire コンポーネントは、ヘルスチェックを自動的に登録します。AppHost はこれを使用して、リソースの準備状況を判断します。

// In AppHost -- WaitFor uses health checks to gate startup
builder.AddProject<Projects.MyApi>("api")
    .WithReference(postgres)
    .WaitFor(postgres);     // Waits for Npgsql health check to pass
カスタムヘルスチェック

Aspire の既定のヘルスチェックとともに、アプリケーション固有のヘルスチェックを追加します。

builder.Services.AddHealthChecks()
    .AddCheck<OrderProcessingHealthCheck>(
        "order-processing",
        tags: ["ready"]);

ヘルスチェックのパターン(ライブネスとレディネス、カスタムチェック、ヘルスチェックの公開)の詳細については、[skill:dotnet-observability] を参照してください。

分散トレーシングの統合

Aspire は ServiceDefaults を通じて OpenTelemetry トレーシングを構成します。トレースは HTTP 境界を越えて自動的に伝播します。カスタムスパンを使用する場合は、次のようにします。

private static readonly ActivitySource s_activitySource = new("MyApp.Orders");

public async Task<Order> ProcessOrderAsync(CreateOrderRequest request, CancellationToken ct)
{
    using var activity = s_activitySource.StartActivity("ProcessOrder");
    activity?.SetTag("order.customer_id", request.CustomerId);

    // Calls to other Aspire services carry trace context automatically
    var inventory = await _httpClient.GetFromJsonAsync<InventoryResponse>(
        $"https+http://inventory-api/api/stock/{request.ProductId}", ct);

    // ... process order
    return order;
}

分散トレーシングの包括的なガイダンス(カスタム ActivitySource、トレースコンテキストの伝播、スパンイベント)については、[skill:dotnet-observability] を参照してください。


コンテナーリソース

コンテナーイメージの追加

Aspire コンポーネントとして利用できないサービスには、任意のコンテナーイメージを追加します。

var seq = builder.AddContainer("seq", "datalust/seq")
    .WithHttpEndpoint(port: 5341, targetPort: 80)
    .WithEnvironment("ACCEPT_EULA", "Y");

// Reference the container from a project
builder.AddProject<Projects.MyApi>("api")
    .WithReference(seq);
永続ボリューム

既定では、Aspire コンテナーは一時ストレージを使用します。再起動後もデータを保持するには、ボリュームを追加します。

var postgres = builder.AddPostgres("pg")
    .WithDataVolume("pg-data")     // Named volume for data persistence
    .AddDatabase("ordersdb");
外部リソース

Aspire が管理していない既存のインフラストラクチャを参照します。

// Connection string from configuration (not an Aspire-managed container)
var existingDb = builder.AddConnectionString("legacydb");

builder.AddProject<Projects.MyApi>("api")
    .WithReference(existingDb);

Aspire と手動のコンテナーオーケストレーションの比較

項目AspireDocker Compose / 手動
構成言語C#(厳密な型付け)YAML
サービスディスカバリー自動(環境変数の注入)手動での DNS/環境変数の構成
ヘルスチェックコンポーネントごとに自動サービスごとに手動で HEALTHCHECK を設定
可観測性OTel とダッシュボードを事前構成OTel コレクターを手動でセットアップ
IDE との統合ホットリロード、F5 デバッグデバッガーを手動でアタッチ
本番環境へのデプロイマニフェストを生成(AZD、K8s)マニフェストを直接作成
.NET 以外のサービスコンテナー参照(統合度は低め)すべての言語を同等にサポート
学習曲線.NET 固有の抽象化業界標準のツール

スタックの大部分が .NET で、標準化された可観測性、サービスディスカバリー、簡素化されたローカル開発環境を求める場合は Aspire を選択してください。きめ細かな制御や多言語サービスが必要な場合、またはチームがすでに Compose/Kubernetes に習熟している場合は、手動のオーケストレーションを選択してください。


主な原則

  • AppHost は開発時のみ使用します -- ローカル開発をオーケストレーションするものであり、本番環境へのデプロイには使用しません
  • 生の接続文字列よりコンポーネントを使用します -- コンポーネントにより、ヘルスチェック、テレメトリ、回復性が自動的に追加されます
  • ServiceDefaults は必須です -- 一貫した可観測性を実現するため、すべての Aspire サービスプロジェクトで参照する必要があります
  • 起動順序の制御には WaitFor を使用します -- 実際の依存関係(スキーマの移行、シードデータなど)に使用し、すべてのリソースには使用しないでください
  • OTel の構成を重複させないでください -- Aspire ServiceDefaults が OpenTelemetry を構成します。手動で構成すると、データが二重に収集されます

エージェント利用時の注意点

  1. Aspire サービスプロジェクトで OpenTelemetry を手動構成しないでください -- ServiceDefaults が OTel プロバイダーをすでに登録しています。手動で .AddOpenTelemetry() を呼び出すと、トレースやメトリクスが重複して収集され、テレメトリのコストが増大します。
  2. Aspire サービスプロジェクトで接続文字列をハードコードしないでください -- builder.AddNpgsqlDbContext<T>("name") または builder.Configuration.GetConnectionString("name") を使用してください。Aspire は環境変数を通じて接続文字列を注入するため、値をハードコードするとサービスディスカバリーが迂回されます。
  3. すべてのリソースに WaitFor を使用しないでください -- 起動が直列化され、起動時間が長くなります。サービスが依存先なしでは実際に起動できない場合(起動時のデータベース移行など)にのみ使用してください。
  4. サービスプロジェクトから Aspire.Hosting.* パッケージを参照しないでください -- ホスティングパッケージは AppHost のみに含めます。サービスプロジェクトではクライアントパッケージ(Aspire.Npgsql、Aspire.StackExchange.Redis など)を使用します。
  5. AppHost を本番環境のホストと混同しないでください -- AppHost はローカル(または CI)で実行し、リソースをオーケストレーションします。本番環境へのデプロイには、生成したマニフェストまたはインフラストラクチャをコードで管理する方法を使用します。
  6. 新しいサービスプロジェクトで AddServiceDefaults() を省略しないでください -- これがないと、サービスディスカバリー、ヘルスチェック、テレメトリが利用できず、Aspire との統合が警告なしに機能しなくなります。

前提条件

  • .NET 10 SDK(または Aspire ワークロードを使用した .NET 8/9)
  • Docker Desktop または Podman(コンテナーリソース用)
  • Aspire ワークロード:dotnet workload install aspire

参考資料

コメント