この記事では、Reliable Web App パターンを実装するためのガイダンスを提供します。 このパターンでは、クラウド移行のために Web アプリを変更 (再プラットフォーム化) する方法について説明します。 Azure Well-Architected Framework のの原則に沿った規範的なアーキテクチャ、コード、および構成のガイダンスを提供します。
.NET 向け信頼性の高い Web アプリ パターンを使用する理由
Reliable Web App パターンは、Web アプリをクラウドに移行するときに Web アプリを再プラットフォーム化する方法を定義する一連の原則と実装手法です。 クラウドで成功するために行う必要がある最小限のコード更新に焦点を当てています。 次のガイダンスでは、全体の例として参照実装を使用します。 このガイダンスは、架空の会社 Relecloud の再プラットフォーム体験に従って、体験のビジネス コンテキストを提供します。 .NET 用の Reliable Web App パターンを実装する前に、Relecloud には、ASP.NET フレームワークを使用するモノリシックオンプレミスチケット Web アプリがありました。
ヒント
信頼性の高い Web アプリ パターンの参照実装 (サンプル) が用意されています。 これは、Relecloud という架空の会社の Reliable Web App 実装の終了状態を表します。 この記事で説明する、コード、アーキテクチャ、構成に対するすべての更新プログラムを取り入れた実稼働グレードの Web アプリです。 この参照実装をデプロイして使用し、信頼性の高い Web アプリ パターンの実装について案内します。
信頼性の高い Web アプリ パターンの実装方法
この記事には、Reliable Web App パターンを実装するためのアーキテクチャ、コード、および構成ガイダンスが含まれています。 次のリンクを使用して、必要な特定のガイダンスに移動します。
- ビジネス コンテキスト します。 このガイダンスをビジネス コンテキストに合わせて調整し、意思決定の再構築を促進する即時および長期的な目標を定義する方法について説明します。
- アーキテクチャのガイダンス。 適切なクラウド サービスを選択し、ビジネス要件を満たすアーキテクチャを設計する方法について説明します。
- コード ガイダンス します。 3 つの設計パターンを実装して、クラウド内の Web アプリの信頼性とパフォーマンス効率を向上させます。再試行、サーキット ブレーカー、Cache-Aside パターンです。
- 構成ガイダンス。 認証と承認、マネージド ID、権限付与された環境、コードとしてのインフラストラクチャ、監視を構成します。
ビジネス コンテキスト
Web アプリのリプラットフォームの最初の手順は、ビジネス目標を定義することです。 サービス レベル目標 (SLO) やコスト最適化の目標など、すぐに目標を設定し、Web アプリケーションの将来の目標も設定する必要があります。 これらの目標は、クラウド サービスの選択と、クラウド内の Web アプリケーションのアーキテクチャに影響します。 99.9% のアップタイムなど、Web アプリのターゲット SLO を定義します。 Web アプリの可用性に影響を与えるすべてのサービスについて、複合 SLA を計算します。
たとえば、Relecloud では売上予測は好調であり、チケット販売 Web アプリの需要の増加が予想されます。 この需要を満たすために、Web アプリケーションの目標を定義しました。
- 低コストで価値の高いコード変更を適用します。
- SLO 99.9%に到達します。
- DevOps プラクティスを採用する。
- コスト最適化環境を作成します。
- 信頼性とセキュリティを向上させます。
Relecloud のオンプレミス インフラストラクチャは、これらの目標を達成するためのコスト効率の高いソリューションではありませんでした。 彼らは、Web アプリケーションを Azure に移行することが、即時および将来の目標を達成するための最もコスト効率の高い方法であると判断しました。
アーキテクチャのガイダンス
信頼性の高い Web アプリ パターンには、いくつかの重要なアーキテクチャ要素があります。 エンドポイント解決を管理するには DNS、悪意のある HTTP トラフィックをブロックする Web アプリケーション ファイアウォール、受信ユーザー要求をルーティングして保護するためのロード バランサーが必要です。 アプリケーション プラットフォームは、Web アプリ コードをホストし、仮想ネットワーク内のプライベート エンドポイントを介してすべてのバックエンド サービスを呼び出します。 アプリケーション パフォーマンス監視ツールは、Web アプリを理解するのに役立つメトリックとログをキャプチャします。
図 1. 信頼性の高い Web アプリ パターンの重要なアーキテクチャ要素。
アーキテクチャの設計
目標復旧時間 (RTO) や目標復旧時点 (RPO) など、復旧メトリックをサポートするようにインフラストラクチャを設計します。 RTO は可用性に影響し、SLO をサポートする必要があります。 RPO を決定し、RPO 満たすようにデータ冗長性 を構成します。
インフラストラクチャの信頼性を選択します。 可用性要件を満たすために必要な可用性ゾーンとリージョンの数を決定します。 複合 SLA が SLO を満たすまで、可用性ゾーンとリージョンを追加します。 信頼性の高い Web アプリ パターンは、アクティブ/アクティブ構成またはアクティブ/パッシブ構成で複数のリージョンをサポートします。 たとえば、参照実装では、アクティブ/パッシブ構成を使用して 99.9% の SLO を満たしています。
複数リージョンの Web アプリの場合は、ビジネスニーズに応じて、アクティブ/アクティブまたはアクティブ/パッシブの構成をサポートするように、トラフィックを 2 番目のリージョンにルーティングするようにロード バランサーを構成します。 2 つのリージョンには同じサービスが必要です。ただし、1 つのリージョンにリージョンを接続するハブ仮想ネットワークがある点が異なります。 ハブアンドスポーク ネットワーク トポロジを導入して、ネットワーク ファイアウォールなどのリソースを一元化および共有します。 仮想マシンがある場合は、要塞ホストをハブ仮想ネットワークに追加して、セキュリティを強化して管理します。 (図 2 を参照してください。)
図 2. 2 つ目のリージョンを設定し、ハブアンドスポーク トポロジを採用した信頼性の高い Web アプリ パターン。
ネットワーク トポロジを選択します。 Web とネットワークの要件に適したネットワーク トポロジを選択します。 複数の仮想ネットワークを使用する場合は、ハブアンドスポーク ネットワーク トポロジを使用します。 コスト、管理、セキュリティの利点と、オンプレミスと仮想ネットワークへのハイブリッド接続オプションが提供されます。
適切な Azure サービスを選択する
Web アプリをクラウドに移行するときは、ビジネス要件を満たし、オンプレミス Web アプリの現在の機能に合った Azure サービスを選択する必要があります。 この配置は、再プラットフォームの作業を最小限に抑えるのに役立ちます。 たとえば、同じデータベース エンジンを維持し、既存のミドルウェアとフレームワークをサポートできるサービスを使用します。 次のセクションでは、Web アプリに適した Azure サービスを選択するためのガイダンスを提供します。
たとえば、クラウドに移行する前の Relecloud のチケット発行 Web アプリは、オンプレミスのモノリシック ASP.NET アプリでした。 これは 2 つの仮想マシンで実行され、SQL Server データベースを使用しました。 Web アプリは、スケーラビリティと機能のデプロイに関する一般的な問題に苦しんでいます。 この出発点、ビジネス目標、SLO がサービスの選択を推進しました。
アプリケーション プラットフォーム:Azure App Service をアプリケーション プラットフォームとして使用します。 Relecloud は、次の理由からアプリケーション プラットフォームとして App Service を選択しました。
- 高いサービス レベル アグリーメント (SLA)。 それは99.9の%の運用環境SLOを満たす高い SLA を有する。
- 管理オーバーヘッドの削減。 これは、スケーリング、正常性チェック、負荷分散を処理するフル マネージド ソリューションです。
- .NET のサポート。 アプリケーションが書き込まれる .NET のバージョンをサポートします。
- コンテナー化機能。 Web アプリは、コンテナー化せずにクラウドに収束できますが、アプリケーション プラットフォームでは、Azure サービスを変更せずにコンテナー化もサポートされます。
- 自動スケーリング。 Web アプリは、ユーザー トラフィックと構成設定に基づいて自動的にスケール インおよびスケールアウトできます。 プラットフォームでは、さまざまなホスティング要件に対応するために、スケールアップまたはスケールダウンもサポートされています。
ID 管理: ID およびアクセス管理ソリューションとして Microsoft Entra ID を使用します。 Relecloud では、次の理由から Microsoft Entra ID を選択しました。
- 認証と承認。 アプリケーションは、コール センターの従業員を認証して承認する必要があります。
- スケーラブル。 Microsoft Entra ID は、大規模なシナリオをサポートするためにスケーリングされます。
- ユーザー ID コントロール。 コール センターの従業員は、既存のエンタープライズ ID を使用できます。
- 承認プロトコルのサポート。 Microsoft Entra ID では、マネージド ID に対して OAuth 2.0 がサポートされています。
データベース: 同じデータベース エンジンを維持できるサービスを使用します。 データ ストアのデシジョン ツリー を使用して、選択をガイドします。 Relecloud の Web アプリでは、オンプレミスの SQL Server を使用していました。 既存のデータベース スキーマ、ストアド プロシージャ、関数を使用したいと考えていました。 Azure ではいくつかの SQL 製品を利用できますが、Relecloud では次の理由から Azure SQL Database を選択しました。
- 確実。 汎用レベルでは、SLA とマルチリージョンの冗長性が高くなります。 高いユーザー負荷をサポートできます。
- 管理オーバーヘッドの削減。 SQL Database には、マネージド SQL データベース インスタンスが用意されています。
- 移行のサポート。 オンプレミスの SQL Server からのデータベース移行をサポートします。
- オンプレミスの構成との整合性。 既存のストアド プロシージャ、関数、およびビューをサポートします。
- 復元。 バックアップとポイントインタイム リストアがサポートされています。
- 専門知識と最小限の手直し。 SQL Database を使用すると、Relecloud は既存の専門知識を活用でき、導入に必要な作業は最小限に抑えられます。
アプリケーションパフォーマンスの監視: アプリケーションのテレメトリを分析するために、Application Insights を使用します。 Relecloud では、次の理由で Application Insights を使用することを選択しました。
- Azure Monitor との統合。 Azure Monitor との最適な統合が提供されます。
- 異常検出。 パフォーマンスの異常が自動的に検出されます。
- トラブルシューティング。 実行中のアプリの問題を診断するのに役立ちます。
- モニタリング。 これにより、ユーザーがアプリをどのように使用しているかに関する情報が収集され、カスタム イベントを簡単に追跡できます。
- 可視性のギャップ。 オンプレミス ソリューションには、アプリケーション パフォーマンス監視ソリューションがありませんでした。 Application Insights は、アプリ プラットフォームとコードとの簡単な統合を提供します。
キャッシュ: Web アプリ アーキテクチャにキャッシュを追加するかどうかを選択します。 Azure Cache for Redis は、プライマリ Azure キャッシュ ソリューションです。 これは、Redis ソフトウェアに基づくマネージドインメモリ データ ストアです。 Relecloud の Web アプリの負荷は、コンサートや会場の詳細の表示に大きく偏っています。 Relecloud では、次の理由から Azure Cache for Redis が追加されました。
- 管理オーバーヘッドの削減。 これはフル マネージド サービスです。
- 速度と音量。 一般的にアクセスされる低速なデータに対して、高いデータ スループットと低待機時間の読み取りを実現します。
- 多様なサポート可能性。 これは、Web アプリのすべてのインスタンスが使用する統合キャッシュの場所です。
- 外部データ ストア。 オンプレミスのアプリケーション サーバーは、VM ローカル キャッシュを実行しました。 このセットアップでは、頻度の高いデータがオフロードされず、データを無効にできませんでした。
- 非スティック セッション。 セッション状態の外部化では、非スティック セッションがサポートされます。
ロード バランサー: PaaS ソリューションを使用する Web アプリケーション は、Web アプリのアーキテクチャと要件に応じて、Azure Front Door、Azure Application Gateway、またはその両方を使用する必要があります。 ロード バランサーのデシジョン ツリーを使用して、適切なロード バランサーを選択します。 Relecloud では、複数のリージョン間でトラフィックをルーティングできるレイヤー 7 ロード バランサーが必要でした。 同社は、99.9%の SLO を満たすために複数リージョンの Web アプリを必要としました。 Relecloud は、次の理由から Azure Front Door を選択しました。
- グローバル負荷分散。 これは、複数のリージョン間でトラフィックをルーティングできるレイヤー 7 ロード バランサーです。
- Web アプリケーション ファイアウォール。 Azure Web Application Firewall とネイティブに統合されます。
- ルーティングの柔軟性。 これにより、アプリケーション チームは、アプリケーションの将来の変更をサポートするイングレス ニーズを構成できます。
- トラフィックアクセラレーション。 エニーキャストを使用して、最も近い Azure プレゼンス ポイントに到達し、Web アプリへの最速のルートを見つけます。
- カスタム ドメイン。 柔軟なドメイン検証でカスタム ドメイン名をサポートします。
- 正常性プローブ。 アプリケーションには、インテリジェントな正常性プローブの監視が必要です。 Azure Front Door は、プローブからの応答を使用して、クライアント要求をルーティングするための最適な配信元を決定します。
- 監視のサポート。 Azure Front Door とセキュリティ パターンの両方に対応するオールインワン ダッシュボードを備えた組み込みのレポートをサポートします。 Azure Monitor と統合するアラートを構成できます。 Azure Front Door を使用すると、アプリケーションは各要求と失敗した正常性プローブをログに記録できます。
- DDoS 保護。 レイヤー 3 から 4 の DDoS 保護が組み込まれています。
- コンテンツ配信ネットワーク。 コンテンツ配信ネットワークを使用するように Relecloud を配置します。 コンテンツ配信ネットワークは、サイト アクセラレーションを提供します。
Web アプリケーション ファイアウォール:Azure Web Application Firewall を使用して、Web での一般的な悪用や脆弱性からの一元的な保護を提供します。 Relecloud では、次の理由で Azure Web アプリケーション ファイアウォールが使用されます。
- グローバル保護。 パフォーマンスを犠牲にすることなく、グローバル Web アプリの保護を強化します。
- Botnet の保護。 チームは、ボットネットに関連するセキュリティ上の問題に対処するための設定を監視および構成できます。
- オンプレミスと同等です。 オンプレミス ソリューションは、IT によって管理される Web アプリケーション ファイアウォールの背後で実行されていました。
- 使いやすさ。 Web アプリケーション ファイアウォールは、Azure Front Door と統合されます。
ストレージの構成: アプリ構成ストレージを Web アプリに追加するかどうかを選択します。 Azure App Configuration は、アプリケーション設定と機能フラグを一元管理するためのサービスです。 App Configuration のベスト プラクティスを確認して、このサービスがアプリに適しているかどうかを判断します。 Relecloud では、ファイルベース構成を、アプリケーション プラットフォームおよびコードと統合されている一元的な構成ストアで置き換えたいと考えていました。 次の理由から、App Configuration をアーキテクチャに追加しました。
- 柔軟性。 機能フラグをサポートしています。 機能フラグを使用すると、ユーザーはアプリの再デプロイを必要とせずに、運用環境で早期プレビュー機能をオプトインまたはオプトアウトできます。
- Git パイプラインのサポート。 構成データの信頼できるソースは、Git リポジトリである必要があります。 パイプラインで、一元的な構成ストアのデータを更新する必要があります。
- マネージド ID のサポート。 マネージド ID をサポートして、構成ストアへの接続を簡素化し、セキュリティで保護します。
シークレット マネージャー: Azure での管理にシークレットを使用している場合は、Azure Key Vault を使用します。 ConfigurationBuilder オブジェクトを使用して、.NET アプリに Key Vault を組み込むことができます。 Relecloud のオンプレミス Web アプリはコード構成ファイルにシークレットを格納しましたが、セキュリティ上の優れた方法は、RBAC と監査の制御をサポートする場所にシークレットを格納することです。 マネージド ID は Azure リソースに接続するための推奨ソリューションですが、Relecloud には管理に必要なアプリケーション シークレットがありました。 Relecloud は、次の理由で Key Vault を使用しました。
- 暗号化。 保存時と転送中の暗号化をサポートします。
- マネージド ID のサポート。 アプリケーション サービスは、マネージド ID を使用してシークレット ストアにアクセスできます。
- 監視とログ記録。 Key Vault は、監査アクセスを容易にし、格納されているシークレットが変更されたときにアラートを生成します。
- 統合。 Key Vault は、Azure 構成ストア (App Configuration) と Web ホスティング プラットフォーム (App Service) とのネイティブ統合を提供します。
ストレージ ソリューション: 要件に基づいて適切なストレージ ソリューションを選択する Azure Storage オプションの を参照してください。 Relecloud のオンプレミスの Web アプリでは各 Web サーバーにディスク ストレージをマウントしていましたが、チームは外部データ ストレージ ソリューションを使用したいと考えていました。 Relecloud は、次の理由で Azure Blob Storage を選択しました。
- セキュリティの強化されたアクセス。 Web アプリは、匿名アクセスでパブリック インターネットに公開されているストレージにアクセスするためのエンドポイントを排除できます。
- 暗号化。 Blob Storage は、保存データと転送中のデータを暗号化します。
- 復元。 Blob Storage では、ゾーン冗長ストレージ (ZRS) がサポートされています。 ゾーン冗長ストレージでは、プライマリ リージョン内の 3 つの Azure 可用性ゾーンにまたがって、データが同期的にレプリケートされます。 各可用性ゾーンは、独立した電源、冷却装置、ネットワークがある別個の物理的な場所にあります。 この構成は、チケット画像の損失に対する回復性を高めます。
エンドポイント セキュリティ:Azure Private Link を使用して、仮想ネットワーク内のプライベート エンドポイント経由でサービスとしてのプラットフォーム (PaaS) ソリューションにアクセスします。 仮想ネットワークとサービスとの間のトラフィックは、Microsoft バックボーン ネットワークをまたがります。 Relecloud は、次の理由で Private Link を選択しました。
- セキュリティ強化された通信。 Private Link を使用すると、アプリケーションは Azure プラットフォーム上のサービスにプライベートにアクセスでき、データ ストアのネットワーク 占有領域を減らして、データ漏えいから保護できます。
- 最小限の労力。 プライベート エンドポイントは、Web アプリが使用する Web アプリ プラットフォームとデータベース プラットフォームをサポートします。 どちらのプラットフォームも既存のオンプレミス構成をミラーリングするため、最小限の変更が必要です。
ネットワーク セキュリティ。 Azure Firewall 使用して、ネットワーク レベルで受信トラフィックと送信トラフィックを制御します。 Azure Bastion を使用して、RDP/SSH ポートを公開することなく、セキュリティが強化された仮想マシンに接続します。 Relecloud はハブ アンド スポーク ネットワーク トポロジを採用し、共有ネットワーク セキュリティ サービスをハブに配置したいと考えていました。 Azure Firewall では、スポークからのすべての送信トラフィックを検査することでセキュリティとネットワーク セキュリティを強化しました。 DevOps サブネット内のジャンプ ホストからのセキュリティ強化デプロイには、Relecloud に Azure Bastion が必要です。
コードのガイダンス
Web アプリをクラウドに正常に移動するには、再試行パターン、サーキット ブレーカー パターン、および Cache-Aside パターンを使用して Web アプリ コードを更新する必要があります。
図 3。 設計パターンの役割。
各設計パターンには、Well-Architected Framework の 1 つ以上の柱に合ったワークロード設計上の利点があります。 実装する必要があるパターンの概要を以下に示します。
再試行パターン。 再試行パターンは、断続的に失敗する可能性のある操作を再試行することで、一時的なエラーを処理します。 このパターンは、他の Azure サービスに対するすべての送信呼び出しに実装します。
サーキット ブレーカー パターン。 サーキット ブレーカー パターンにより、アプリケーションが一時的ではない操作を再試行できなくなります。 このパターンは、他の Azure サービスに対するすべての送信呼び出しに実装します。
Cache-Aside パターン。 Cache-Aside パターンは、データ ストアからキャッシュにオンデマンドでデータを読み込みます。 このパターンは、データベースに対する要求に実装します。
設計パターン | 信頼性 (RE) | セキュリティ (SE) | コスト最適化 (CO) | オペレーショナル エクセレンス (OE) | パフォーマンス効率 (PE) | WAF の原則のサポート |
---|---|---|---|---|---|---|
再試行パターン | ✔ | RE:07 | ||||
サーキット ブレーカー パターン | ✔ | ✔ |
RE:03 RE:07 PE:07 PE:11 |
|||
Cache-Aside パターンの | ✔ | ✔ |
RE:05 PE:08 PE:12 |
再試行パターンを実装する
一時的なサービスの中断に対処するために、再試行パターンをアプリケーション コードに追加します。 これらの中断は、一時的な障害と呼ばれます。 一時的な障害は、通常は数秒以内に解決されます。 再試行パターンを使用すると、失敗した要求を再送信できます。 また、再試行の間の遅延と、失敗を認める前の試行回数を構成することもできます。
組み込みの再試行メカニズムを使用します。 ほとんどの Azure サービスが提供する組み込みの再試行メカニズムを使用して、実装を迅速化します。 たとえば、参照実装では、Entity Framework Core の 接続の回復性を使用して、SQL Database への要求で再試行パターンを適用します。
services.AddDbContextPool<ConcertDataContext>(options => options.UseSqlServer(sqlDatabaseConnectionString, sqlServerOptionsAction: sqlOptions => { sqlOptions.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(3), errorNumbersToAdd: null); }));
再試行プログラミング ライブラリを使用します。 HTTP 通信の場合は、Polly や
Microsoft.Extensions.Http.Resilience
などの標準的な回復性ライブラリを統合します。 これらのライブラリは、外部 Web サービスとの通信を管理するために不可欠な包括的な再試行メカニズムを提供します。 たとえば、参照実装では、Polly を使用して、コードがIConcertSearchService
オブジェクトを呼び出すオブジェクトを構築するたびに再試行パターンを適用します。private void AddConcertSearchService(IServiceCollection services) { var baseUri = Configuration["App:RelecloudApi:BaseUri"]; if (string.IsNullOrWhiteSpace(baseUri)) { services.AddScoped<IConcertSearchService, MockConcertSearchService>(); } else { services.AddHttpClient<IConcertSearchService, RelecloudApiConcertSearchService>(httpClient => { httpClient.BaseAddress = new Uri(baseUri); httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json"); httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "Relecloud.Web"); }) .AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetCircuitBreakerPolicy()); } } private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() { var delay = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(500), retryCount: 3); return HttpPolicyExtensions .HandleTransientHttpError() .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .WaitAndRetryAsync(delay); }
サーキット ブレーカー パターンを実装する
サーキット ブレーカー パターンを使用して、一時的な障害ではないサービスの中断を処理します。 サーキット ブレーカー パターンは、アプリケーションが応答しないサービスに継続的にアクセスすることを防ぎます。 アプリケーションを解放し、CPU サイクルの無駄を防ぐのに役立ちます。これにより、アプリケーションはエンド ユーザーのパフォーマンス整合性を維持します。
たとえば、参照実装では、API に対するすべての要求にサーキット ブレーカー パターンが適用されます。
HandleTransientHttpError
ロジックを使用して、安全に再試行できる HTTP 要求を検出しますが、指定した期間の集計エラーの数を制限します。
private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
キャッシュアサイド パターンを実装する
キャッシュアサイド パターンを Web アプリに追加して、メモリ内データ管理を改善します。 このパターンにより、データ要求を処理し、キャッシュと永続ストレージ (データベースなど) の間の整合性を確保する責任がアプリケーションに割り当てられます。 これにより、応答時間が短縮され、スループットが向上し、さらなるスケーリングの必要性が軽減されます。 また、プライマリ データストアの負荷も軽減され、信頼性とコストの最適化が向上します。 キャッシュアサイド パターンを実装するには、次の推奨事項に従います。
キャッシュを使用するようにアプリケーションを構成します。 運用アプリでは、分散 Redis Cache を使用する必要があります。 このキャッシュは、データベース クエリを減らすことでパフォーマンスを向上させます。 また、ロード バランサーがトラフィックを均等に分散できるように、非スティック セッションも有効になります。 参照実装では、分散 Redis キャッシュを使用します。
AddAzureCacheForRedis
メソッドは、Azure Cache for Redis を使用するようにアプリケーションを構成します。private void AddAzureCacheForRedis(IServiceCollection services) { if (!string.IsNullOrWhiteSpace(Configuration["App:RedisCache:ConnectionString"])) { services.AddStackExchangeRedisCache(options => { options.Configuration = Configuration["App:RedisCache:ConnectionString"]; }); } else { services.AddDistributedMemoryCache(); } }
必要性の高いデータをキャッシュします。 必要性の高いデータに Cache-Aside パターンを適用して、その有効性を高めます。 Azure Monitor を使用して、データベースの CPU、メモリ、ストレージを追跡します。 これらのメトリックは、Cache-Aside パターンを適用した後に、より小さなデータベース SKU を使用できるかどうかを判断するのに役立ちます。 たとえば、参照実装では、Upcoming Concerts ページで使用される、必要性の高いデータがキャッシュされます。
GetUpcomingConcertsAsync
メソッドは、SQL Database から Redis キャッシュにデータをプルし、キャッシュに最新のコンサート データを設定します。public async Task<ICollection<Concert>> GetUpcomingConcertsAsync(int count) { IList<Concert>? concerts; var concertsJson = await this.cache.GetStringAsync(CacheKeys.UpcomingConcerts); if (concertsJson != null) { // There is cached data. Deserialize the JSON data. concerts = JsonSerializer.Deserialize<IList<Concert>>(concertsJson); } else { // There's nothing in the cache. Retrieve data // from the repository and cache it for one hour. concerts = await this.database.Concerts.AsNoTracking() .Where(c => c.StartTime > DateTimeOffset.UtcNow && c.IsVisible) .OrderBy(c => c.StartTime) .Take(count) .ToListAsync(); concertsJson = JsonSerializer.Serialize(concerts); var cacheOptions = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) }; await this.cache.SetStringAsync(CacheKeys.UpcomingConcerts, concertsJson, cacheOptions); } return concerts ?? new List<Concert>(); }
キャッシュ データを最新の状態に保ちます。 最新のデータベース変更と同期するように、定期的なキャッシュ更新をスケジュールします。 データのボラティリティを使用し、ユーザーは最適なリフレッシュ レートを決定する必要があります。 この方法により、アプリケーションは Cache-Aside パターンを使用して、迅速なアクセスと最新の情報の両方を提供できます。 たとえば、参照実装は 1 時間だけデータをキャッシュし、
CreateConcertAsync
メソッドを使用して、データが変更されたときにキャッシュ キーをクリアします。public async Task<CreateResult> CreateConcertAsync(Concert newConcert) { database.Add(newConcert); await this.database.SaveChangesAsync(); this.cache.Remove(CacheKeys.UpcomingConcerts); return CreateResult.SuccessResult(newConcert.Id); }
データの一貫性を確保します。 データベース書き込み操作の直後にキャッシュを更新するメカニズムを実装します。 イベント駆動の更新または専用のデータ管理クラスを使用して、キャッシュの一貫性を確保します。 キャッシュとデータベースの変更を一貫して同期することは、キャッシュ アサイド パターンの主要な部分です。 参照実装では、
UpdateConcertAsync
メソッドを使用して、キャッシュ内のデータの整合性を維持します。public async Task<UpdateResult> UpdateConcertAsync(Concert existingConcert), { database.Update(existingConcert); await database.SaveChangesAsync(); this.cache.Remove(CacheKeys.UpcomingConcerts); return UpdateResult.SuccessResult(); }
構成ガイダンス
以降のセクションでは、構成の更新プログラムの実装に関するガイダンスを提供します。 各セクションは、Well-Architected フレームワークの 1 つ以上の柱と一致します。
構成 | 信頼性 (RE) | セキュリティ (SE) | コスト最適化 (CO) | オペレーショナル エクセレンス (OE) | パフォーマンス効率 (PE) | WAF の原則のサポート |
---|---|---|---|---|---|---|
認証と承認を構成する | ✔ | ✔ |
SE:05 OE:10 |
|||
マネージド ID を実装する | ✔ | ✔ |
SE:05 OE:10 |
|||
Rightsize 環境 | ✔ |
CO:05 CO:06 |
||||
自動スケーリングを実装する | ✔ | ✔ | ✔ |
RE:06 CO:12 PE:05 |
||
リソースのデプロイの自動化 | ✔ | OE:05 | ||||
監視を実装する | ✔ | ✔ | ✔ |
OE:07 PE:04 |
認証と承認を構成する
Web アプリケーションを Azure に移行する場合は、ユーザーの認証と承認のメカニズムを構成します。 次の推奨事項に従ってください。
ID プラットフォームを使用します。 Microsoft ID プラットフォームを使用して、Web アプリ認証を設定します。 このプラットフォームは、1 つの Microsoft Entra ディレクトリ、異なる組織の複数の Microsoft Entra ディレクトリ、および Microsoft ID またはソーシャル アカウントを使用するアプリケーションをサポートします。
アプリケーション登録を作成します。 Microsoft Entra ID では、プライマリ テナントにアプリケーションを登録する必要があります。 アプリケーションの登録は、Web アプリにアクセスするユーザーがプライマリ テナントに ID を持っていることを確認するのに役立ちます。
プラットフォームの機能を使用します。 ユーザー認証とデータ アクセスにプラットフォームの機能を使用することで、カスタムの認証コードの必要性を最小限に抑えます。 たとえば、App Service には組み込みの認証サポートが用意されているため、Web アプリで最小限またはまったくコードを記述しながらユーザーをサインインさせ、データにアクセスできます。
アプリケーションで承認を強制します。 RBAC を使用して、アプリケーション ロール 最小限の特権を割り当てます。 重複を回避し、明確にするために、さまざまなユーザー アクションに対して特定のロールを定義します。 ユーザーを適切なロールにマップし、必要なリソースとアクションにのみアクセスできることを確認します。
ストレージに対しては一時的なアクセスを優先します。 一時的なアクセス許可を使用して、不正アクセスや侵害から保護します。 たとえば、Shared Access Signature (SAS) を使用して、アクセスを一定期間に制限できます。 一時的なアクセス権を付与するときに、ユーザー委任 SAS を使用してセキュリティを最大化します。 これは、Microsoft Entra ID の資格情報を使用し、永続的なストレージ アカウント キーを必要としない唯一の SAS です。
Azure で承認を強制します。 Azure RBAC を使用して、ユーザー ID に最小限の特権を割り当てます。 Azure RBAC では、ID がアクセスできる Azure リソース、それらのリソースでできること、アクセスできる領域を定義します。
永続的で高度なアクセス許可は避けます。 Microsoft Entra Privileged Identity Management を使用して、特権操作の Just-In-Time アクセスを許可します。 たとえば、開発者は多くの場合、データベースの作成/削除、テーブル スキーマの変更、ユーザーのアクセス許可の変更を行うために、管理者レベルのアクセス権を必要とします。 Just-In-Time アクセスを使用すると、ユーザー ID は特権タスクを実行するための一時的なアクセス許可を受け取ります。
マネージド ID を使用する
マネージド ID をサポートするすべての Azure サービスに使用します。 マネージド ID を使用すると、Azure リソース (ワークロード ID) は、資格情報の管理を必要とせずに、他の Azure サービスに対する認証と対話を行うことができます。 移行を簡略化するには、ハイブリッド システムとレガシ システム用のオンプレミス認証ソリューションを引き続き使用できますが、できるだけ早くマネージド ID に移行する必要があります。 マネージド ID を実装するには、次の推奨事項に従います。
適切な種類のマネージドIDを選択します。 同じアクセス許可のセットを必要とする複数の Azure リソースがある場合は、ユーザー割り当てのマネージド ID を優先します。 この方法は、各リソースに対してシステム割り当てマネージド ID を作成し、それらのすべてに同じアクセス許可を割り当てるよりも効率的です。 そうでない場合は、システム割り当てのマネージド ID を使用します。
最小特権を構成します。 Azure RBAC 使用して、データベースの CRUD アクションやシークレットへのアクセスなど、操作に不可欠なアクセス許可のみを付与します。 ワークロード ID のアクセス許可は永続的であるため、ワークロード ID にジャスト・イン・タイムまたは短期のアクセス許可を提供することはできません。 Azure RBAC が特定のシナリオに対応していない場合は、Azure サービス レベルのアクセス ポリシーで Azure RBAC を補完します。
残りのシークレットのセキュリティを提供します。 残りのシークレットを Azure Key Vault に格納します。 各 HTTP 要求中ではなく、アプリケーションの起動時に Key Vault からシークレットを読み込みます。 HTTP 要求内での高頻度のアクセスにより、Key Vault のトランザクション制限を超える可能性があります。 アプリケーション構成を Azure App Configuration に格納します。
参照実装では、SQL データベース接続文字列の Authentication
引数を使用して、App Service がマネージド ID Server=tcp:my-sql-server.database.windows.net,1433;Initial Catalog=my-sql-database;Authentication=Active Directory Default
を使用して SQL データベース に接続 できるようにします。
DefaultAzureCredential
を使用して、Web API がマネージド ID を使用して Key Vault に接続できるようにします。
builder.Configuration.AddAzureAppConfiguration(options =>
{
options
.Connect(new Uri(builder.Configuration["Api:AppConfig:Uri"]), new DefaultAzureCredential())
.ConfigureKeyVault(kv =>
{
// Some of the values coming from App Configuration
// are stored in Key Vault. Use the managed identity
// of this host for the authentication.
kv.SetCredential(new DefaultAzureCredential());
});
});
Rightsize 環境
各環境のニーズを超えることなく、Azure サービスのパフォーマンス レベル (SKU) を使用します。 環境を適切にサイズ変更するには、次の推奨事項に従います。
コストを見積もる。 Azure 料金計算ツールを使用して、各環境のコストを見積もります。
運用環境のコスト最適化。 運用環境には、運用に必要なサービス レベル アグリーメント (SLA)、機能、スケールを満たす SKU が必要です。 リソースの使用状況を継続的に監視し、実際のパフォーマンス ニーズに合わせて SKU を調整します。
運用前環境のコスト最適化。運用前環境 低コストのリソースを使用し、azure Dev/Test 価格 などの割引を利用する必要があります。 これらの環境では、不要なサービスを無効にする必要があります。 同時に、実稼働前環境が運用環境 環境と十分に類似していることを確認して、リスクが発生しないようにします。 このバランスを維持することで、不要なコストを発生させずにテストを効果的に維持できます。
コードとしてのインフラストラクチャ (IaC) を使用して SKU を定義します。 IaC を実装することで、環境に基づいて適切な SKU を動的に選択してデプロイします。 このアプローチにより、一貫性が向上し、管理が簡略化されます。
たとえば、参照実装では Bicep パラメーターを使用して、よりコストの高いレベル (SKU) を運用環境にデプロイします。
var redisCacheSkuName = isProd ? 'Standard' : 'Basic'
var redisCacheFamilyName = isProd ? 'C' : 'C'
var redisCacheCapacity = isProd ? 1 : 0
自動スケーリングを実装する
自動スケーリングは、Web アプリが回復性と応答性を維持し、動的なワークロードを効率的に処理できるようにするのに役立ちます。 オートスケールを実装するには、次の推奨事項に従います。
スケールアウトを自動化します。Azure オートスケールを使用して、実稼働環境での水平スケーリングを自動化します。 アプリケーションがさまざまな負荷を処理できるように、主要なパフォーマンス メトリックに基づいてスケールアウトするように自動スケール ルールを構成します。
スケーリング トリガーを調整します。 アプリケーションのスケーリング要件に慣れていない場合は、初期スケーリング トリガーとして CPU 使用率を使用します。 スケーリング トリガーを調整して、RAM、ネットワーク スループット、ディスク I/O などの他のメトリックを含めます。 目標は、Web アプリケーションの動作を合わせることで、パフォーマンスを向上させることです。
スケールアウト バッファーを指定します。 最大容量に達する前にトリガーするようにスケーリングのしきい値を設定します。 たとえば、100% に達するまで待機するのではなく、CPU 使用率 85% で実行するようにスケーリングを構成します。 このプロアクティブなアプローチは、パフォーマンスを維持し、潜在的なボトルネックを回避するのに役立ちます。
リソースのデプロイの自動化
自動化を使用して、すべての環境に Azure のリソースとコードをデプロイおよび更新します。 次の推奨事項に従ってください。
コードとしてのインフラストラクチャを使用します。 継続的インテグレーションと継続的デリバリー (CI/CD) パイプラインを使用して、インフラストラクチャをコード としてデプロイします。 Azure には、すべての Azure リソースに Bicep、ARM (JSON)、Terraform テンプレート 事前構築済みテンプレートが用意されています。
継続的インテグレーション/継続的デプロイ (CI/CD) パイプラインを使用します。 CI/CD パイプラインを使用して、ソース管理からさまざまな環境 (テスト、ステージング、運用など) にコードをデプロイします。 Azure DevOps を使用している場合は、Azure Pipelines を使用します。 GitHub プロジェクトに GitHub Actions を使用します。
単体テストの統合。 App Services にデプロイする前に、パイプライン内のすべての単体テストの実行と受け渡しに優先順位を付けます。 SonarQube などのコード品質およびカバレッジ ツールを組み込んで、包括的なテスト カバレッジを実現します。
モック フレームワークを採用する。 外部エンドポイントを含むテストでは、モック フレームワークを使用します。 これらのフレームワークを使用すると、シミュレートされたエンドポイントを作成できます。 これにより、実際の外部エンドポイントを構成し、環境間でテスト条件を統一する必要がなくなります。
セキュリティ スキャンを実行します。 静的アプリケーション セキュリティ テスト (SAST) を使用して、ソース コードのセキュリティの欠陥とコーディング エラーを見つけます。 さらに、ソフトウェア構成分析 (SCA) を実行して、サードパーティのライブラリとコンポーネントのセキュリティ リスクを調べます。 これらの分析用のツールは、GitHub と Azure DevOps の両方に簡単に統合できます。
監視を実装する
アプリケーションとプラットフォームの監視を実装して、Web アプリのオペレーショナル エクセレンスとパフォーマンス効率を向上させます。 監視を実装するには、次の推奨事項に従います。
アプリケーション テレメトリを収集します。 Azure Application Insights 自動侵入 を使用して、要求スループット、平均要求期間、エラー、依存関係の監視など、アプリケーション テレメトリを収集します。 このテレメトリを使用するためにコードを変更する必要はありません。
参照実装では、NuGet パッケージ
Microsoft.ApplicationInsights.AspNetCore
からのAddApplicationInsightsTelemetry
を使用して、テレメトリ収集 有効にします。public void ConfigureServices(IServiceCollection services) { ... services.AddApplicationInsightsTelemetry(Configuration["App:Api:ApplicationInsights:ConnectionString"]); ... }
カスタム アプリケーション メトリックを作成します。 カスタム アプリケーション テレメトリには、コードベースのインストルメンテーションを使用します。 コードに Application Insights SDK を追加し、Application Insights API を使用します。
参照実装では、カートのアクティビティに関連するイベントに関するテレメトリが収集されます。
this.telemetryClient.TrackEvent
は、カートに追加されたチケットをカウントします。 イベント名 (AddToCart
) を指定し、concertId
とcount
を持つディクショナリを指定します。this.telemetryClient.TrackEvent("AddToCart", new Dictionary<string, string> { { "ConcertId", concertId.ToString() }, { "Count", count.ToString() } });
プラットフォームを監視します。 サポートされているすべてのサービスの診断を有効にします。 関連付けのために、アプリケーション ログと同じ宛先に診断を送信します。 Azure サービスはプラットフォーム ログを自動的に作成しますが、診断を有効にした場合にのみ保存します。 診断をサポートするサービスごとに、診断設定を有効にします。
参照実装をデプロイする
このリファレンス実装では、オンプレミスの ASP.NET アプリケーションから Azure へのシミュレートされた移行を開発者に案内し、初期導入フェーズで必要な変更を強調します。 この例では、架空の会社である Relecloud のコンサート チケット販売アプリケーションを使用し、オンプレミスの Web アプリケーションを通じてチケットを販売しています。 Relecloud では、Web アプリケーションに次の目標を設定しています。
- 低コストで価値の高いコード変更を実装します。
- 99.9%の SLO を達成します。
- DevOps プラクティスを採用する。
- コスト最適化環境を作成します。
- 信頼性とセキュリティを強化します。
Relecloud は、オンプレミスのインフラストラクチャがこれらの目標を達成するためのコスト効率の高いソリューションではないと判断しました。 彼らは、Web アプリケーションを Azure に移行することが、即時および将来の目標を達成するための最もコスト効率の高い方法であると判断しました。 次のアーキテクチャは、Relecloud の Reliable Web App パターン実装の終了状態を表しています。