🔖

マイクロサービスを作らない人による .NET Aspire の概要説明(普通に便利)

2024/06/12に公開

Microsoft Build 2024 で .NET Aspire のバージョン 1.0 がリリースされました。
ここでは、その .NET Aspire の説明をしたいと思います。

公式ドキュメントは以下になります。

https://learn.microsoft.com/ja-jp/dotnet/aspire/get-started/aspire-overview

ここでは公式ドキュメントとはちょっと違った切り口で解説していこうと思います。

.NET Aspire とは

.NET Aspire は、複数のサービスで構成されるアプリケーション開発やデプロイを支援するツールやライブラリの集合体です。
ここでいうサービスは自分たちで開発するマイクロサービスのこともあれば、既存のサービスやミドルウェアを指すこともあります。つまり単一の Web アプリが Redis や SQL Server に依存するといったケースでも .NET Aspire の恩恵を受けることが出来ます。
また .NET Aspire はアプリケーション開発フレームワークではないので、既存のアプリケーションに組み込んで使うことが出来るようになっています。

.NET Aspire を使う .NET アプリケーションのソリューションには以下の 2 つのプロジェクトが含まれています。

  • アプリ名.AppHost プロジェクト
    • アプリ ホスト プロジェクトと呼ばれます。
    • 主にアプリ モデル (後述) を定義するためのプロジェクトです。その他に共通で設定する環境変数やパラメーターなどもこのプロジェクトで定義します。
  • アプリ名.ServiceDefaults プロジェクト
    • サービス デフォルト プロジェクトと呼ばれます。
    • 各プロジェクトに共通する設定を定義するためのプロジェクト。このプロジェクトは必須ではないですが、プロジェクトで参照して AddServiceDefaults メソッドと MapDefaultEndpoints メソッドの呼び出しを追加することで、アプリケーション全体で共通の設定を適用することが出来ます。

アプリ ホスト プロジェクト

アプリ ホスト プロジェクトは慣例的に アプリ名.AppHost という名前のプロジェクトとして作成されます。
このアプリケーションの目的はアプリ モデルというものを組み立てるのと、アプリケーションに含まれているサービス全体で共有されるような設定を一元管理することです。
アプリ モデルは、個人的には .NET Aspire で一番重要な概念だと思います。このアプリ モデルを元に .NET Aspire は様々な便利な機能を提供しています。

アプリモデル

アプリ モデルはアプリ ホスト プロジェクトで DistributedApplication クラスとして定義されます。アプリ モデルを組み立てるためには IDistributedApplicationBuilder インターフェースに対して Add追加するリソースの種類 という名前のメソッドを呼び出すことでリソースを追加して組み立てることが出来ます。

リソースには以下の 3 種類があります。

  • プロジェクト
  • コンテナー イメージ
  • 実行可能ファイル

プロジェクトは AddProject メソッドで追加されmす。AddContainerAddExecutable を使ってコンテナー イメージや実行可能ファイルを追加することも出来ます。

コンテナー イメージを便利に使うためのショートカットとして AddRedis メソッドや AddSqlServer メソッドなどが Aspire.Hosting.RedisAspire.Hosting.SqlServer という名前の NuGet パッケージなどで提供されています。ただ、あくまで簡易的に呼べるようにしているだけなので、自分でコンテナー イメージ名や、そのコンテナー イメージで公開されるエンドポイントの定義などを自分で組み立てることでも対応できます。

実行可能ファイルを便利に使うためのショートカットとして AddNpmAppAddNodeApp などのメソッドが Aspire.Hosting.NodeJs という名前の NuGet パッケージなどで提供されています。これを使って ReactVue などの SPA アプリや Node.js を使って作られたバックエンド アプリとも連携が可能になっています。これも npm コマンドや node コマンドを叩くためのショートカットなので自分で実行可能ファイルを呼び出すためのコードを書くことでも対応できます。

例えば Redis をキャッシュサービスとして使い SQL Server を RDBMS として使う Web アプリケーションを表すアプリ ホスト プロジェクトの Program.cs は以下のようになります。

Program.cs
var builder = DistributedApplication.CreateBuilder(args);

// Redis を追加
var redis = builder.AddRedis("redis");
// SQL Server を追加して sampleDb というデータベースを追加
var sqlServer = builder.AddSqlServer("sqlserver");
var sampleDb = sqlServer.AddDatabase("sampleDb");

// Web アプリケーションを追加
builder.AddProject<Projects.AspireApp1_Web>("webapp")
    // 外部向けの公開エンドポイントがあることを明示
    .WithExternalHttpEndpoints()
    // Web アプリケーションが Redis と SQL Server を使用することを明示
    .WithReference(redis)
    .WithReference(sampleDb);

builder.Build().Run();

AddProject メソッドの型引数に渡している Projects.AspireApp1_Web という型はアプリ ホスト プロジェクトのプロジェクト参照に対して AspireApp1.Web という名前のプロジェクトを追加することで自動生成される型です。このようにして、プロジェクト間の関連性やプロジェクトが依存する外部のミドルウェアやサービスなどを C# のコードで定義しています。

また Aspire.Hosting.Azure.サービス名 という名前のパッケージでは、デバッグ実行時に自動的に紐づけられた Azure のサブスクリプションに対してリソースを作成することが出来るようになっています。これによって、開発時に Azure のリソースを使って開発を行う際に手動でリソースを作り、接続文字列を取得してきて構成するといった手間を省くことが出来ます。

このように複数のサービスから構成されるアプリケーションの関連性を定義することで .NET Aspire は様々な便利な機能をプロジェクトに提供するといった設計になっています。

サービス デフォルト プロジェクト

サービス デフォルト プロジェクトは慣例的に アプリ名.ServiceDefaults という名前のプロジェクトとして作成されます。ここには .NET Aspire が提供する機能を使うための共通の設定を定義されています。Extensions.cs という名前のファイルに AddServiceDefaults 拡張メソッドや MapDefaultsEndpoints 拡張メソッドが定義されています。

Visual Studio 等を使ってプロジェクトに .NET Aspire の機能を組み込むと自動的にサービス デフォルト プロジェクトへの参照が追加されて AddServiceDefaults 拡張メソッドと MapDefaultEndpoints 拡張メソッドが呼び出されるようになっています。

このプロジェクトを参照に追加して AddServiceDefaults 拡張メソッドと MapDefaultEndpoints 拡張メソッドを呼び出すことで、以下の機能を .NET Aspire を使うプロジェクトで利用可能になります。

  1. OpenTelemetry のメトリックとトレースの構成を行います。
    • OTEL_EXPORTER_OTLP_ENDPOINT 環境変数が設定されているときは UseOtelpExporeter が呼び出されて OpenTelemetry のエクスポーターが設定されます。
    • .NET Aspire のアプリ ホストプロジェクトから実行を行うと、この環境変数が自動的に設定されて後述するダッシュボードからメトリックやトレースを確認することが出来るようになります。
    • AddOpenTelemetryExporeters メソッドを変更して任意のエクスポーターを追加することも出来ます。コード例として APPLICATIONINSIGHTS_CONNECTION_STRING が環境変数に設定されている場合に Azure Monitor に出力するように構成するコードがコメントとして記載されています。
  2. デフォルトのヘルス チェック エンドポイントを追加します。
    1. /health というヘルスチェックエンドポイントと /alive という死活監視のためのエンドポイントが追加されます。
      • 開発環境でのみ上記のエンドポイントは有効になります。
      • 本番環境上でもヘルスチェック エンドポイントが必要な場合は「ASP.NET Core の正常性チェック」を参考にして自分で実装することが出来ます。
  3. サービス検出の構成
    • .NET のサービス検出 を使ってサービスの検出を行うための設定を行います。
    • サービス検出はエンドポイントを IP アドレスやホスト名ではなく スキーマ://_エンドポイント名.サービス名スキーマ://サービス名 のように指定することでサービスの実際のホスト名や IP アドレスを隠蔽することが出来るように構成されます。
      • 指定方法の例: https://_dashboard.cataloghttps+http://catalog など
  4. サービス検出を使用する HttpClient の構成
    • 3 のサービス検出を使用する HttpClient の構成を行います。

.NET Aspire が提供する機能

繰り返しになりますが .NET Aspire は、アプリケーション フレームワークではなく、アプリケーション開発やデプロイを支援するツールやライブラリの集合体です。これまで述べたアプリ ホスト プロジェクトやサービス デフォルト プロジェクトを使って、これから説明する様々な機能を提供しています。

提供している機能は大きく分類して以下の 2 つに分けることが出来ると思います。

  1. 開発・テスト時に便利な機能
  2. デプロイを支援する機能

.NET Aspire を使う際には開発時に便利な機能だけを使ってデプロイを支援する機能は使わないといった選択も可能です。デプロイを支援する機能まで使うと .NET Aspire の機能をフル活用できるので受けられる恩恵も大きいですが、自分に合わない機能がある場合は取捨選択をして使うことも出来ます。

では、それぞれにどんな機能があるか見ていきましょう。

開発・テスト時に便利な機能

開発時に便利な機能は以下のようなものがあります。

アプリ ホスト プロジェクトを通じて以下のような機能が提供されます。

  1. アプリ ホスト プロジェクトの実行時にアプリ モデルの定義に基づいてサービスを起動する
  2. メトリックとトレースのダッシュボード
  3. パラメーターや環境変数などの一元管理
  4. サービス解決のための環境変数の自動設定

そして、サービス デフォルト プロジェクトを参照に追加して AddServiceDefaults メソッドと MapDefaultEndpoints 拡張メソッドを呼び出すことで以下のような機能が提供されます。

  1. OpenTelemetry のメトリックとトレースの構成
  2. デフォルトのヘルス チェック エンドポイントの追加
  3. サービス検出の構成
  4. サービス検出を使用する HttpClient の構成

これらの機能を使うことで開発時に便利な機能を使うことが出来ます。

さらにユニット テスト フレームワークのテストケースの中でもアプリ ホスト プロジェクトを起動する API が提供されています。これによって DB や複数サービスやプロジェクトを含む一式を起動して、そこに対して結合テストのようなテストを行うことが出来ます。

また、デバッグ実行時にアプリ モデルで定義された各種リソースの状況のモニタリングや、OpenTelemetry のメトリックやトレースや、アプリケーションに設定されている環境変数・ポート番号などを確認するためのダッシュボードが提供されています。これは、ローカル開発用に最適化されているため OpenTelemetry のデータは永続化されずにオンメモリで保持されるだけになります。個人的には見た目も良いので本番でも使えてログも保存してくれたら嬉しいとは思いますが、現状はメインの用途は開発時にローカルで使用することを想定しているようです。
しかし、要望が多いため独立の Docker イメージも公開されていて独立して使うことも出来ます。

ダッシュボードの見た目は以下のようなものになります。

デプロイを支援する機能

デプロイを支援する機能は以下のようなものがあります。

  1. 組込みで Azure Developer CLI に対応していて Azure Container Apps にデプロイすることが出来ます。
  2. Aspir8 という OSS を使用して Kubernates のクラスターにデプロイすることが出来ます。
  3. アプリ モデルからマニフェストを生成することが出来ます。
    • マニフェストにはデプロイに必要なためのリソースの定義が含まれます。
    • マニフェストを解析してデプロイを自動化するツールを作ることが出来ます。

組込みの Azure Container Apps へのデプロイを使用してもいいですし、Kubernates がお好みの場合は Aspir8 を使ってもいいです。若干いばらの道ですが自分でマニフェストを元に任意の場所へデプロイする機能を作っても良いです。
もしくは、デプロイ機能は使用せずに、従来の方法でアプリケーションはデプロイしても構いません。

.NET Aspire を使ったアプリケーション自体はサービス デフォルト プロジェクトを参照に追加していたり、Aspire 関連の NuGet パッケージをいくつか参照に追加はしていますが、基本的には通常の .NET アプリケーションと同じなので .NET のアプリケーションをデプロイできる場所にデプロイを行うことが出来ます。

まとめ

ここまでで、.NET Aspire の概要やアプリ ホスト プロジェクト、サービス デフォルト プロジェクトの説明をしました。また、.NET Aspire が提供する機能についても説明しました。

100% の機能を網羅しているわけではないですが、.NET Aspire の全体像は以下のようなイメージになります。

ポイントは自分の作成しているアプリケーションから参照しているのは、サービス デフォルト プロジェクトだけであり、そこもアプリケーションに規定の構成を追加するだけに使用されています。
.NET Aspire はアプリケーション開発フレームワークではなく、各種ツールやライブラリなどの集合体であり、アプリケーション開発やデプロイを支援するためのものです。.NET Aspire を使ったからといって ASP.NET Core MVC/Razor Pages/Blazor Web App やワーカー サービスなどのアプリケーションの作りが変わることはありません。Program.cs に少しだけ .NET Aspire の規定の構成に従った構成を追加するだけで、.NET Aspire の恩恵を受けることが出来ます。基本的に、そこ以外のアプリケーションコードには影響を与えません。

個人的には、今までの単一プロジェクトとして作っていたようなアプリケーションでもローカルで開発をする際に SQL Server などのミドルウェアを使っていたり、Azure のサービスを使っていたりするようなケースでも .NET Aspire を適用すると Visual Studio でコードを開いて実行するだけで、ミドルウェアまわりの構成も自動的に行われて開発が開始できる環境が整うという点は非常に強力だと思っています。1 つ前の記事でも、この利点を説明しています。興味があるかたは是非見てみてください。

https://zenn.dev/microsoft/articles/dotnet-aspire-minimal

この概要を読んで .NET Aspire に興味を持った方は Microsoft Learn のドキュメントやトレーニングコンテンツを確認してみてください。

それでは、良い .NET Aspire ライフを!

Microsoft (有志)

Discussion