Aspire による Runtime と Observability

Lino がサービス、web apps、インフラリソースを生成した後、Aspire はそれらを可視性のある形でローカル実行するのに役立ちます。Observability は贅沢ではありません。APIs、データベース、cache、messaging、workers が健全かどうかを示します。

events、Outbox、workers、Redis、RabbitMQ、複数モジュールを持つアプリケーションでは、多くの問題は画面だけには現れません。logs、queues、jobs、migrations、パラメータ、runtime リソースに現れます。このセクションでは、生成されたファイルとしてだけでなく、実行中のシステムとしてソリューションを見る方法を示します。

Aspire による実行

AppHost はソリューションのローカル実行を集約します。サービス、web apps、PostgreSQL、Redis、RabbitMQ、workers などの依存関係を起動します。

dotnet run --project src/Aspire/AppHost/<ProjectName>.AppHost.csproj

dashboard を使って logs、変数、endpoints、リソースの状態を確認します。サービスの起動に失敗した場合は、AppHost と、それが注入する依存関係から確認を始めてください。

Aspire はローカルのトポロジを可視化します。APIs、web apps、データベース、cache、message broker、workers が関連リソースとして表示されます。この表示により、誤った connection string、不足しているパラメータ、endpoint のないサービス、まだ起動していない依存関係など、手動実行では隠れがちな設定ミスを見つけやすくなります。

  • Logs: 初期化エラー、認証失敗、migrations の問題、worker のメッセージを追跡します。
  • Endpoints: ポート、URLs、health checks、web apps と APIs へのリンクを確認します。
  • Parameters: 各サービスへ伝播される secrets と変数を検証します。
  • Dependencies: アプリケーションを診断する前に、Redis、RabbitMQ、データベースが provision 済みであることを確認します。

データベースリソース

Lino が生成するサービスは通常、独自の DbContexts、migrations、connection strings を持ちます。モジュール型システムでは、各モジュールが期待されるデータベース/schema を使っているか、migrations が正しい場所に適用されているかを検証してください。

  • 環境ごとの connection strings を確認します。
  • 新しい schema に依存するフローをテストする前に migrations を実行します。
  • 接続失敗と query 時間を監視します。
  • ローカル実行で本番データベースを使わないでください。

単純なサービスでは、データベースはサービスに付随します。モジュール型サービスでは、データベースはサービスに属しますが、各モジュールが独自の schema、DbContext、migrations、scripts を持つことがあります。この分離は運用にも反映する必要があります。migrations を適用するときは、実行前にサービス、モジュール、provider、環境を確認してください。

データベース障害は API エラーとして現れることが多いですが、原因は AppHost、connection string、未適用の migration、存在しない schema、またはローカル資格情報にある場合があります。そのため診断は、Aspire のパラメータ、有効なデータベースリソース、適用済み migration、正しい DbContext、期待されるモジュールを呼び出している endpoint という一連の流れから始める必要があります。

Redis と cache

Redis は、有効化された templates に応じて、cache、一時状態、tokens、rate limiting、その他のリソースに使用できます。cache はパフォーマンスを向上させますが、invalidation と eventual consistency を導入します。

キー、有効期限、データの出所を文書化してください。暗号化、有効期限、アクセス制御を理解せずに、機密性の高い secrets を cache に保存してはいけません。

プロジェクトが分散 cache を使う場合、複数インスタンスで値を共有できるため、水平スケールに役立ちます。ローカルのインメモリ cache だけを使う場合は、各プロセスが独自のコピーを保持します。この違いは、本番環境での動作、負荷試験、データの invalidation に影響します。

質問重要な理由
cache されたデータの出所は何か?期限切れまたは invalidation されたときに値をどう再計算するかを定義します。
許容できる TTL はどれくらいか?システムが潜在的に古いデータをどれくらいの時間許容するかを決めます。
cache は tenant 別、ユーザー別、またはグローバルか?コンテキスト間のデータ漏えいと、不適切に設計されたキーを防ぎます。

RabbitMQ と messaging

messaging は integration events と非同期通信を支えます。Outbox を使うと、アプリケーションはトランザクションと同じ瞬間にメッセージを publish することに依存せず、worker が再試行できます。

  • 生成された exchanges、queues、bindings を確認します。
  • 停滞したメッセージと非アクティブな consumers を監視します。
  • idempotent な handlers を設計します。
  • correlation logs を使ってメッセージの経路を追跡します。

integration events が有用なのは、producer がすべての consumers を待つ必要がないためです。ただし、その分の複雑さは運用へ移ります。メッセージは遅延し、consumers は失敗し、payloads は変化し、handlers は複数回実行される可能性があります。フローのドキュメントでは、どの event が publish され、誰が consume し、どのローカル状態が更新されるのかを明確にする必要があります。

Shadow Entities はこの observability に依存します。tenant またはユーザーの entity が event によって他のモジュールへ複製される場合、consumer の失敗によりローカルコピーが古いままになることがあります。システムは event、メッセージ、handler、consumer モジュールのデータベースで実行された更新を診断できる必要があります。

Hangfire Dashboard

background jobs が有効な場合、Hangfire Dashboard は recurring jobs、失敗、retries、Outbox 処理の実行状況を確認するのに役立ちます。

共有環境では dashboard を保護してください。重要な運用情報を公開するため、認証と認可なしで公開すべきではありません。

dashboard は診断ツールとして使い、logs とメトリクスの代替にはしないでください。queues、試行回数、実行履歴は表示されますが、job が失敗した理由を完全に調査するには、correlation id、構造化 logs、ビジネスコンテキストが引き続き必要です。

  • Retries: 失敗が一時的なものか、それとも job が無期限に失敗し続けるのかを確認します。
  • Recurring jobs: 間隔、バッチ、平均実行時間を確認します。
  • Outbox: 停滞したメッセージ、再処理、例外を出した handlers を観察します。
  • Security: payloads やエラーが機密データを明らかにする可能性があるため、アクセスを制限します。

Workers とバックグラウンド処理

Workers は HTTP リクエストをブロックすべきでないタスクを実行します。メッセージ送信、Outbox 処理、クリーンアップ、同期、外部連携などです。

  • 量に適したバッチを使います。
  • retries と失敗処理を定義します。
  • 再処理できるだけの十分なコンテキストを付けてエラーを記録します。
  • 恒久的な失敗を汎用的な logs に隠さないでください。

worker を追加するときは、頻度、バッチサイズ、失敗時の動作、ドメインへの影響も定義してください。数秒ごとに 100 件を読む worker は、日次 job とは異なる運用特性を持ちます。どちらも実際の量に応じて観測し、サイズを決める必要があります。

ユーザーへ即時応答が必要な処理を background で実行しないでください。worker は後続タスク、連携、通知、再処理、保守に使います。ユースケースがトランザクション完了のために結果へ依存する場合は、同期フローとして扱うか、ユーザーに見える中間状態をモデル化してください。

処理されていないエラーが発生しました。 再読み込み 🗙