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 は後続タスク、連携、通知、再処理、保守に使います。ユースケースがトランザクション完了のために結果へ依存する場合は、同期フローとして扱うか、ユーザーに見える中間状態をモデル化してください。
