エクスポート (0) 印刷
すべて展開

Windows Azure クラウド サービスで大規模なサービスを設計するためのベスト プラクティス

更新日: 2014年1月

執筆者: Mark Simms、Michael Thomassy

寄稿者: Jason Roth、Ralph Squillace

校閲者: Brad Calder、Dennis Mulder、Mark Ozur、Nina Sarawgi、Marc Mercuri、Conor Cunningham、Peter Carlin、Stuart Ozer、Lara Rubbelke、Nicholas Dritsas

概要

クラウド コンピューティングは分散コンピューティングです。処理を分散するには、選択するプラットフォームにかかわらず、慎重な計画と配信が必要です。このドキュメントの目的は、実際の顧客シナリオに基づいて、Windows Azure および SQL データベース上にスケーラブルなアプリケーションを構築するための綿密なガイダンスを提供することです。その際、Platform-as-a-Service (PaaS) のアプローチを利用します (そのようなアプリケーションは、Web ロールとワーカー ロールを使用して、Windows Azure クラウド サービスとして構築されます)。

Important重要
メモ: このドキュメントのすべてのベスト プラクティス ガイダンスは、Windows Azure 上で実稼働コードを実行している顧客との緊密な連携から得られたものです。このドキュメントでは、v1.6 SDK リリースに基づいて Windows Azure クラウド サービス (PaaS) プラットフォームについて説明します。Windows Azure の Web サイトWindows Azure の仮想マシン (IaaS) などの機能は対象にしていません。

このドキュメントは、Windows Azure アプリケーションを構築するための基盤となる設計概念、Windows Azure プラットフォームの機能、制限と機能、コア Windows Azure サービスを使用するためのベスト プラクティスについて説明します。主に扱うのは、緩い一貫性を持つ分散データ ストアに適用可能なアプリケーションです (厳密に一貫性があるか、高密度のマルチテナント データ モデルではありません)。

Windows Azure へのアプリケーションとサービスの移行は、次のようなさまざまな理由で利点があります。

  • 資本支出を節約したり、資本支出を運用支出に統合する (capex から opex へ)。

  • 要求と容量をより密接に一致させることにより、コストを削減する (また、効率を高めます)。

  • インフラストラクチャの障壁を低減または除去することによって、アジリティと製品化までの時間を改善する。

  • モバイル デバイスなどの新しい市場に対象を広げる。

  • 世界中の地理的に分散したデータセンターにいる対象ユーザーをサポートできる新しいアプリケーションを構築することにより、非常に大きなスケールのクラウド コンピューティングの利点を享受する。

Windows Azure 用の新しいアプリケーションを開発するか、既存のアプリケーションの一部またはすべてを Windows Azure に移植することについて、多くの優れた技術的な理由が考えられます。環境には実装上の選択肢が多数あるため、正しい実装アプローチを選択するには、具体的なアプリケーション パターンを慎重に評価する必要があります。一部のアプリケーションは、Platform-as-a-Service (PaaS) アプローチである Windows Azure クラウド サービスに適していますが、他のアプリケーションでは、Windows Azure の仮想マシンなど、部分的または全体的な Infrastructure-as-a-Service (IaaS) アプローチによる恩恵を受けます。また、特定のアプリケーション要件では、両方を併用することが最も適している場合があります。

Windows Azure クラウド サービスの利点を最大限に高めるために、アプリケーションには、次の 3 種類の重要な特徴のうち 1 つ以上が必要です (これらの特徴すべてがアプリケーションに存在する必要はありません。次の特徴が 1 つでもあれば、Windows Azure を活用することにより、投資に対する高い効果が得られる可能性があります。しかし、これらの特徴がどれもないワークロードは、Windows Azure クラウド サービスに最適ではない可能性があります)。

アプリケーションを評価する際の重要な特徴は次のとおりです。

  • 柔軟な要求。Windows Azure に移行する重要な価値命題の 1 つは、柔軟な要求です。これは、アプリケーションから容量を追加または削除 (スケールアウトとスケールイン) して、動的なユーザーの要求により近づけるための能力です。ワークロードの要求が静的で固定的な場合 (たとえば、ユーザーやトランザクションの数などが静的な場合)、Windows Azure クラウド サービスのこの利点が最大化されません。

  • 分散したユーザーとデバイス。Windows Azure 上で実行することにより、アプリケーションをすぐにグローバルに配置できます。ワークロードに、1 つの場所 (1 つのオフィスなど) で働く固定のユーザー ベースがある場合、クラウド配置では、最適な投資回収率が得られない可能性があります。

  • 分割可能なワークロード。クラウド アプリケーションはスケールアウトによって拡張され、より小さな単位で容量が追加されます。アプリケーションがスケール アップ (たとえば、大規模なデータベースやデータ ウェアハウス) や、特殊な専用のワークロード (たとえば、大規模な統一高速ストレージ) に依存している場合、クラウド内で実行できるように、分解 (分割) してスケールアウト サービスで実行されるようにする必要があります。これは、ワークロードによっては簡単でない場合があります。

繰り返しますが、アプリケーションを評価するとき、Windows Azure クラウド サービスに移行するか Windows Azure クラウド サービス上で構築することによって高い投資収益率が得られるのは、ワークロードが、Windows Azure クラウド サービスのような Platform-as-a-Service 環境で際立つ、上記 3 つの特徴のうち 1 つのみを持っている場合です。3 つの特徴すべてを備えているアプリケーションは、非常に高い投資収益率が得られる可能性があります。

設計概念

Windows Azure 用にアプリケーションを設計することに関する多くの側面は、オンプレミスの開発から非常になじみがあるものですが、基盤となるプラットフォームとサービスの動作にはいくつかの重要な違いがあります。こうした違いを把握し、その結果、プラットフォームに逆らうのではなく、プラットフォームに合わせて設計する方法を理解することは、クラウドの柔軟な拡張という期待に応えるアプリケーションを提供するうえできわめて重要です。

ここでは、Windows Azure クラウド サービスなど、Platform-as-a-Service (PaaS) 環境向けの、大規模で、広く分散されたスケールアウト アプリケーションを構築する際のきわめて重要な設計ポイントである、5 つの重要な概念について説明します。これらの概念を理解することは、Windows Azure クラウド サービスで動作するだけでなく、その中で成長し、投資に対してできる限り多くの利益が得られるアプリケーションを設計および構築するのに役立ちます。このドキュメントの後半で説明する設計上の留意事項と選択のすべては、これら 5 つの概念に結びついています。

また、これらの留意事項とベスト プラクティスの多くは .NET アプリケーションを通じた視点によるものですが、基になる概念とアプローチの大部分は、言語やプラットフォームに依存しません。

スケールアップではなくスケールアウト

オンプレミス アプリケーションから Windows Azure クラウド サービスへの移行における重要な変更点は、アプリケーションの拡張方法に関連しています。大規模なアプリケーションを構築するための従来の方法は、スケールアウト (ステートレスなアプリケーション サーバーと Web サーバー) およびスケールアップ (より大規模なマルチコアまたは大容量メモリ システム、データベース サーバーを購入し、より大規模なデータ センターを構築するなど) の組み合わせに依存しています。クラウドでは、スケールアップは現実的な選択肢ではありません。真にスケーラブルなアプリケーションを実現するための唯一の方法は、スケールアウト用に明示的に設計することです

オンプレミス アプリケーションの要素の多くは、既にスケールアウト (Web サーバー、アプリケーション サーバー) に適用できるため、課題は、スケールアップ サービスに依存するアプリケーションの側面を明確にし、それをスケールアウトで実装できるように変換 (またはマッピング) することです。スケールアップに依存する第 1 の候補は、一般にリレーショナル データベース (SQL Server または Windows Azure SQL データベース) です。

従来のリレーショナル設計の中心になっているのは、強い整合性とトランザクション動作を使用した、全体に整合性があるデータ モデル (単一サーバーのスケールアップ) です。このバッキング ストアに対して拡張性を提供するための従来のアプローチは、「すべてをステートレスにし」、状態を管理する役割をスケールアップ SQL サーバーに先延ばしするというものでした。

しかし、SQL Server が備えるきわめて高いスケーラビリティは、拡張の面では真に柔軟とは言えません。つまり、きわめて応答性が高いリソース可用性ではなく、高価な移行フェーズを経て、要求を大幅に超えた容量を備えた、より大規模なサーバーを購入する必要があり、そのたびにスケールアップを拡張することになります。また、過去のミッドレンジのハードウェアを拡張するときには、コストが指数的に跳ね上がります。

Windows Azure クラウド サービスのアーキテクチャ基盤はスケールアウトであるため、アプリケーションはスケールアウト データ ストアで動作するように設計されている必要があります。これは、データをより小さな部分 (それぞれがデータ パーティションまたはスケールアウト単位に収まる) に明示的に分割し、分散したデータ要素間の一貫性を管理するなどの、設計上の課題を意味します。これによって、スケールアップ向けに設計する際の欠点の多くを避けることができる方法で、分割を通じて拡張が達成されます。

よく知られたスケールアップ手法から、スケールアウト データと状態管理に移行することは、クラウド向けに設計するうえで通常、最大の難関です。このドキュメントの多くは主に、これらの課題への対処と、Windows Azure クラウド サービスと、永続的データを管理するための Windows Azure SQL データベースの、拡張性があり柔軟な機能を利用できるアプリケーションの設計について説明します。

すべてのものには制限があります: 拡張に向けた構成

独自にデータ センターを運営する場合、制御の程度も選択肢の数もほぼ無制限です。物理的な設備 (空調、電気供給、フロア スペース) からインフラストラクチャ (ラック、サーバー、ストレージ、ネットワークなど)、構成 (ルーティング トポロジ、オペレーティング システム、インストール) に至るまで、すべてを自分で制御できます。

この制御の程度が、資本コスト、運用コスト、人件費、時間など、コストに結びつきます。敏捷で常に変化する環境で詳細をすべて管理するためのコストが、仮想化に向かう理由の中心であり、クラウドに移行する際の重要な側面です。これらのプラットフォームでは、制御の手段を放棄する見返りとして、配置や管理のコストが削減され、敏捷さが向上します。これらのプラットフォームで課される制約は、使用可能なコンポーネントとサービスの規模 (容量、スループットなど) が、提供されている固定のサービスに制限されるということです。

これは、貿易における大量輸送が、主に運送用コンテナーに基づいているのに似ています。これらのコンテナーは、さまざまな輸送手段 (船、列車、トラック) で輸送され、さまざまな標準サイズ (最大長 53 フィート) が使用できます。輸送する積み荷の量が最大のトレーラーの容量を超える場合は、次のいずれかを使用する必要があります。

  • 複数のトレーラーを使用する。そのためには、複数のコンテナーに収まるように積み荷を分割し、トレーラーの運送を調整することになります。

  • 特殊な運送方法を使用する。標準のコンテナーで運送できない (大きすぎる、かさばるなど) 積み荷の場合は、荷船など、非常に特殊な方法を使用する必要があります。このような方法は、一般に標準の積み荷運送よりもはるかに高額になります。

Windows Azure (およびクラウド コンピューティング一般) にこのたとえを当てはめると、すべてのリソースに制限があります。個々のロール インスタンス、ストレージ アカウント、クラウド サービス、データ センターのどれをとっても、Azure で利用可能なすべてのリソースには上限があります。データ センターで利用可能なストレージの量など、上限がきわめて高いこともありますが (最大の貨物船が 10,000 個のコンテナーを運送できるのに似ています)、有限です。

これを念頭に置くと、拡張するためには、負荷を分割し、複数のスケール単位 (複数の VM、データベース、ストレージ アカウント、クラウド サービス、データ センター) にまたがって組み立てることが必要になります。

このドキュメントでは、スケール単位という用語を、(a) 定義された負荷の程度を処理し、(b) それをまとめて組み立てることで追加の負荷を処理することができる、リソースのグループを指すために使用します。たとえば、Windows Azure ストレージ アカウントの最大サイズは 100 TB です。100 TB を超えるデータを格納する必要がある場合は、複数のストレージ アカウント (つまり、ストレージのスケール単位を 2 つ以上) を使用する必要があります。

Azure の主要な各サービスとコンポーネントの容量についての一般的な設計ガイドラインと、拡張性を追加するためにこれらのサービスを構成するための推奨されるアプローチを、以降のセクションで説明します。

可用性のための設計

非常に回復力の高いアプリケーションをオンプレミスで構築するために、きわめて大量の時間、エネルギー、知的資本が注ぎ込まれてきました。これは、一般に、アプリケーションを下位のコンポーネント (アプリケーション サーバー、ネットワーク) と上位のコンポーネント (データベース、SAN) に分割し、それぞれに障害モードに対する回復力を持たせることに要約されます。

ここで、障害モードとは、(a) 障害状態のシステムを観察することと、(b) 障害の原因の組み合わせを指します。たとえば、不適切に設定されたパスワードの更新が原因でアクセスできないデータベースは障害モードです。障害状態は接続できないこと (接続が拒否される、資格情報が受け付けられない) であり、障害原因は、アプリケーション コードに正しく伝えられなかったパスワードの更新です。

下位のコンポーネントでは、弱く結合された冗長性と、外部のシステムによって管理されるシステムへの "統合" を通じて回復力が提供されます。たとえば、ロード バランサーの背後に追加の Web サーバーを配置します。各 Web サーバーは互いに同じであり (これにより、元になる Web サーバー イメージを複製するだけで新たな容量を追加できます)、ロード バランサーによって管理されるアプリケーション全体に統合されます。

上位のコンポーネントでは、コンポーネント間の "統合" が厳密に管理された密結合の冗長性によって回復力が提供されます。次に例を示します。

  • SQL Server。アクティブ/パッシブ クラスターの一部として冗長な SQL Server インスタンスを追加するには、複数のノードの間でトランザクション上の一貫性のあるフェールオーバーを提供するために、互換性のある (つまり同一の) ハードウェアを慎重に選択し、共有ストレージ (SAN など) を用意する必要があります。

  • 電源。冗長電源の提供は非常に高度な例であり、ローカル (プライマリ電源とセカンダリ電源をオンボードのハードウェアで切り替えることのできる複数の電源を備えたサーバー) および中央 (電源喪失に備えた補助発電機) の広範な問題を軽減するために連携して機能する複数のシステムが必要です。

密結合のアプローチに基づく回復力ソリューションでは、熟練のスタッフ、専用のハードウェア、および慎重な構成とテストが要求されるため、"同じものを追加" するだけの疎結合のアプローチに比べて本質的にコストが高くなります。つまり、難しいだけでなくコストもかかるソリューションです。

このようにハードウェア プラットフォームに高い回復力を確保しようとするアプローチは、"チタン製の卵の殻" にたとえることができます。卵の中身を保護するために殻を頑丈な (そして高価な) チタンの層で覆うという考え方です。

経験が示すように (詳細については http://www.mvdirona.com/jrh/TalksAndPapers/JamesRH_Lisa.pdf を参照してください)、大規模なシステム (Windows Azure クラスのデータ システムなど) では、多数の可動部が含まれるために常にどこかが故障しています。Windows Azure プラットフォームは、この制約に抗うのではなくそれを前提に作られており、ノード レベルのエラー イベントからの自動復旧に依存しています。この設計方針は、すべてのコア Windows Azure サービスに貫かれており、Windows Azure の可用性モデルを使用するアプリケーションを設計するための鍵になります。

Windows Azure に移行すると、回復力の話題が、インフラストラクチャの冗長性の課題からサービスの冗長性の課題に変わります。オンプレミスで可用性の計画の中心だったコア サービスの多くは、Azure では何もしなくても機能し続けます。

  • SQL データベースでは、トランサグション一貫性のある複数のデータのレプリカが自動的に維持され、データベースでノード レベルのエラーが発生すると、一貫性のあるセカンダリに自動的にフェールオーバーします。回復力を提供するためには多くの時間とコストがかかるオンプレミス環境とは対照的です。

  • Windows Azure ストレージでは、一貫性のある複数のデータのコピーが自動的に維持され (詳細については、http://sigops.org/sosp/sosp11/current/2011-Cascais/11-calder-online.pdf を参照してください)、記憶域ボリュームでノード レベルのエラーが発生すると、一貫性のあるセカンダリに自動的にフェールオーバーします。SQL データベースと同様、記憶域の回復力を直接管理するオンプレミスのクラスターや SAN とは対照的です。

とは言え、このセクションのタイトルは可用性であり、回復力ではありません。回復力は、SLA の範囲内でユーザーに継続的に価値を提供するというテーマの一部にすぎません。サービスのすべてのインフラトラクチャ コンポーネントが正常であっても、想定される数のユーザーに対処できなければ、サービスの可用性は維持されず、価値も提供されません。

モバイル中心のワークロードやソーシャル中心のワークロード (モバイル デバイス アプリケーションを含むパブリック Web アプリケーションなど) は、固定ユーザーを対象とするワークロードに比べてはるかに動的な傾向があるため、バースト イベントやピーク時の負荷に対処するためのより高度なアプローチが必要になります。このドキュメントでは、全体を通じて、Windows Azure アプリケーションの可用性を設計する際に注意する必要がある主な概念について詳しく説明します。以下にその概要を示します。

  • Windows Azure のサービスやコンポーネントでは、それぞれ特定のサービス レベル契約 (SLA) が提供されますが、その SLA が、アプリケーションを実行するために必要な可用性の基準に直接関連しない場合もあります。ユーザーに提供できる全体的な可用性を把握するためには、システムのすべてのコンポーネント、それらの可用性の SLA、およびそれらの相互作用を把握することが重要です。

    • 単一インスタンスのロールなど、SLA を損なう単一障害点を回避します。

    • 特定のサービスがオフラインになったり使用できなくなったりした場合の影響を軽減するために複数のコンポーネントを構成します (別のコンポーネントにフォールバックします)。

  • Windows Azure のサービスやコンポーネントではエラー (短期の一時的なイベントまたは長期的なイベント) が発生する可能性があります。そのため、エラーを適切に処理するようにアプリケーションを作成する必要があります。

    • 一時的なエラーに対しては、再接続や作業の再送信のための適切な再試行メカニズムを用意します。

    • その他のエラー イベントに対しては、そのエラー イベントに関する豊富なインストルメンテーションを用意し (エラーを報告します)、適切なエラー メッセージをユーザーに返します。

    • 可能であれば、別のサービスまたはワークフローにフォールバックします。たとえば、データを SQL データベースに挿入する要求が (無効なスキーマなどの一時的でない理由で) 失敗した場合は、シリアル化された形式で BLOB ストレージに書き込みます。これにより、データを永続的にキャプチャして、スキーマの問題が解決された後でデータベースに送信できます。

  • すべてのサービスにピーク時の容量があります。それは、明示的な場合もあれば (調整ポリシーやピーク時の負荷の漸近線によるものなど)、暗黙的な場合もあります (システム リソースの制限によるものなど)。

    • リソースの制限に達した場合にサービス レベルを徐々に下げるようにアプリケーションを設計し、適切な対処によってユーザーへの影響を和らげます。

    • 適切なバックオフ/再試行ロジックを実装して、サービスに対する "コンボイ" の影響を回避します。適切なバックオフ メカニズムがないと、ピーク イベントが発生した後に下流のサービスが遅れを取り戻せなくなります (アプリケーションがサービスに負荷を与え続けて、調整ポリシーが呼び出されたりリソースが枯渇したりするため)。

  • ラピッド バースト イベントが発生する可能性があるサービスでは、ピーク デザイン ロードの超過に (シェディング機能を使用するなどして) 適切に対処する必要があります。

    • 人体が極度の寒さにさらされた場合に末端への血流が制限されるように、極端に負荷が高いときには比較的重要性が低いサービスを間引くようにサービスを設計します。

    • アプリケーションによって提供されるサービスは、ビジネスにとっての重要性がそれぞれ異なるため、適用される SLA も同じとは限りません。

これらの高レベルの概念については、各コア Windows Azure サービスのセクションで、各サービスまたはコンポーネントの可用性の目標と、可用性のための設計の推奨事項と共に、詳しく説明します。大規模なアプリケーションでは引き続きデータ センターが単一障害点になることに注意してください。データ センターは、電源 () からシステム エラー () まで、インフラストラクチャやアプリケーションのさまざまな問題によってダウンします。比較的まれではありますが、最高レベルのアップタイムを必要とするアプリケーションは、複数の冗長なデータ センターに配置する必要があります。

アプリケーションを複数のデータ センターに配置するには、インフラストラクチャとアプリケーションで次のような機能が必要になります。

  • サービスのユーザーを (地理的な場所、ユーザー パーティション、またはその他のアフィニティ ロジックに基づいて) 適切なデータ センターにルーティングするアプリケーション ロジック。

  • データ センター間でのアプリケーションの状態の同期とレプリケーション。適切なレベルの待機時間と一貫性が確保されている必要があります。

  • アプリケーションの自律的な配置。データ センター間の依存関係を最小限に抑えます (データ センター A の障害によってデータ センター B でも障害が発生するような状況を避けます)。

ビジネス継続性のための設計

可用性と同様、(データ センターが損失した場合に) 災害復旧ソリューションを提供するには、かなりの時間、労力、およびコストが必要でした。ここでは、システム障害およびデータ損失が発生した場合に (その原因がシステムにあるかユーザーにあるかに関係なく) ビジネス継続性を提供するための方法と注意事項について説明します。"災害復旧" という用語は、データベース コミュニティにおいて、実装のアプローチに関する特別な意味を持つようになっています。

ビジネス継続性は以下の機能によって提供されます。

  • インフラストラクチャで致命的な障害が発生した場合に重要なビジネス システム (永続的な状態を操作するアプリケーション) へのアクセスおよびその可用性を維持する。

  • インフラストラクチャで致命的な障害が発生した場合に重要なビジネス データ (永続的な状態) へのアクセスおよびその可用性を維持する。

  • オペレーター エラー (過失による削除、変更、破損など) が発生した場合に重要なビジネス データ (永続的な状態) の可用性を維持する。

従来は、最初の 2 つの機能は地理的な災害復旧 (geo-DR) のコンテキストで提供され、3 番目の機能はデータのバックアップと復元の領域に含まれていました。

Windows Azure は、主要なアプリケーションを世界中のデータ センターにすばやく分散配置できるようにすることにより、重要なビジネス システムの可用性の方程式を大きく変えます。実際、地理的に分散されたアプリケーションを導入するプロセスは、単一のクラウド サービスを導入するプロセスとほとんど変わりません。

残る主な課題は、永続的な状態へのアクセスの管理です。一般に、複数のデータ センターにまたがって永続的な状態サービス (Windows Azure ストレージ、SQL データベースなど) にアクセスする場合は、待機時間の増加や変動によって最適な結果が得られません。また、データ センターで障害が発生した場合にビジネス継続性の要件が満たされません。

回復力と同様、多くの Windows Azure サービスには、自動地理分散の機能が用意されています (またはこれから導入される予定です)。たとえば、特に指定しない限り、Windows Azure ストレージ (BLOB、キュー、またはテーブル) への書き込みはすべて自動的に別のデータ センターにレプリケートされます (各データ センターには、同じ地理的領域内に固有の "ミラー" があります)。これにより、従来の災害復旧ソリューションを提供するために必要な時間と労力が Windows Azure では大幅に削減されます。永続的な状態を管理するコア Windows Azure サービスの地理分散機能の概要については後ほど説明します。

ユーザー エラーやオペレーター エラーが発生した場合にビジネス継続性を維持するためには、アプリケーションの設計で考慮する必要がある追加の注意事項がいくつかあります。Windows Azure ストレージには、ストレージ分析機能 (後ほど説明します) による限定された監査機能が用意されていますが、特定の時点への復元の機能は用意されていません。データが誤って削除されたり変更されたりした場合の回復力が必要なサービスでは、アプリケーション中心のアプローチを検討する必要があります (BLOB を定期的に別のストレージ アカウントにコピーするなど)。

SQL データベースには、データの履歴スナップショットを維持するための基本的な機能が用意されています (データベース コピー、bacpac によるインポート/エクスポートなど)。これらのオプションについては、このドキュメントの後半で詳しく説明します。

密度はコスト

Windows Azure プラットフォームでは、柔軟な拡張が実現されるため、需要と供給を一致させることができます (ピーク時の負荷に備えて追加の容量を大量に確保する必要がなくなります)。

柔軟な拡張により、コストは次の要素によって決まるようになります。

  • ソリューションで使用するスケール単位の数 (VM、ストレージ アカウントなど (拡張のための構成))

  • それらのスケール単位によって実行される作業の効率

ここでは、一定の容量で実行できる作業の量をアプリケーションの密度と呼びます。より密度の高いサービスやフレームワークを使用すると、同じリソースでより多くの作業を実行できます。つまり、密度を改善することによって、配置する容量 (およびコスト) を削減したり、同じ容量でより多くの負荷を吸収したりすることができます。密度は主に次の 2 つの要因によって決まります。

  • スケール単位内で作業が実行される効率。これは、従来の形式のパフォーマンス最適化です (スレッドの競合とロックの管理、アルゴリズムの最適化、SQL クエリのチューニング)。

  • スケール単位間の作業の連携の効率。現在、システムの構成要素の増加および小型化が進んでいるため、それらを効率的にまとめることがシステムの効率化においてきわめて重要になります。そのためには、SOAP メッセージング スタック (WCF など)、ORM (Entity Framework など)、TDS 呼び出し (SQL クライアント コード)、オブジェクトのシリアル化 (データ コントラクト、JSON など) など、コンポーネント間の通信のためのフレームワークとツールが必要です。

拡張性の高い効率的な Windows Azure サービスの提供においては、1 つのコンピューター (またはデータベース) に対して使用される従来の最適化手法に加えて、分散通信や分散操作の最適化が重要になります。以下に主要な最適化を示します。これらについては後のセクションで詳しく説明します。

  • chatty ではなく chunky。すべての分散操作 (ネットワーク呼び出しが発生する操作) には、パケットのフレーミング、シリアル化、処理などの一定のオーバーヘッドがあります。オーバーヘッドを最小限に抑えるには、バッチ処理を活用して、多数の "chatty" な操作ではなく少数の "chunky" な操作を使用するようにします。細かい操作をバッチ処理すると、待機時間が増加し、データ損失の可能性が高くなることに注意してください。適切なバッチ処理の例を以下に示します。

    • SQL。1 つのバッチで複数の操作を実行します。

    • REST サービスと SOAP サービス (WCF など)。chatty な RPC スタイルではなくメッセージ中心の操作インターフェイスを活用します。可能であれば REST ベースのアプローチを検討します。

    • Windows Azure ストレージ (BLOB、テーブル、キュー)。複数の更新を個別にパブリッシュせずにバッチでパブリッシュします。

  • シリアル化の影響。データをコンピューター間で移動する場合 (および永続的なストレージから出し入れする場合) は、一般にデータをワイヤ形式にシリアル化する必要があります。大規模なシステムでは、この操作の効率 (操作に要する時間と領域) がすぐにアプリケーション全体のパフォーマンスを左右するようになります。

    • 効率的なシリアル化フレームワークを活用します。

    • デバイスとの通信や相互運用可能な (人間が判読できる) アプリケーションに JSON を使用します。

    • サービス間通信に効率的なバイナリ シリアル化 (protobufAvro など) を使用します (両方のエンドポイントを制御できる場合)。

  • 効率的なフレームワークを使用します。洗練された機能を数多く備えた開発用フレームワークが多数出回っていますが、使用しない機能のためにパフォーマンスが犠牲にされていることがよくあります。

    • 汎用インターフェイスの背後にサービス API とクライアント API を分離して、置き換えたり並べて評価したりできるようにします (静的ファクトリまたは制御の反転コンテナーを使用します)。たとえば、特定の実装 (Windows Azure Caching など) ではなく汎用インターフェイスを操作して、プラグイン可能なキャッシュ レイヤーを提供します。

Windows Azure クラウド サービスの検証

前のセクションでは、Windows Azure によって提供されるクラウド ファブリックを活用するアプリケーションを作成するための主な設計概念と設計観点を紹介しました。ここでは、このプラットフォームの主要なサービスと機能について、それらの機能、拡張の範囲、および可用性のパターンを示しながら説明します。

Windows Azure のすべてのサービス コンポーネントとインフラストラクチャ コンポーネントで、限られた容量と可用性の SLA が提供されるため、アプリケーションのスケーラビリティの目標やエンド ユーザー SLA に適した設計上の選択を行うためには、これらの制限と動作を理解しておくことが重要です。ここでは、各コア Windows Azure サービスについて、機能と目的、密度、スケーラビリティ、および可用性の 4 つの主要な観点から検討します。

Windows Azure サブスクリプション

Windows Azure サブスクリプションは、管理、課金、およびサービス クォータの基本単位です。各 Windows Azure サブスクリプションには、サポートに連絡することによって増やすことができる一連の既定のクォータがあります。これは、知らぬ間に超過料金が発生したりリソースを消費したりするのを防ぐことを目的としています。

各サブスクリプションには、アカウント所有者と、一連の共同管理者が存在します。共同管理者は、Microsoft アカウント (以前の Live ID) によって承認され、管理ポータルからサブスクリプションのリソースを完全に制御できます。たとえば、ストレージ アカウントの作成、クラウド サービスの配置、構成の変更、共同管理者の追加/削除などを行うことができます。

Windows Azure Management API (REST ベースの Web サービス) は、Windows Azure サービスの作成、構成、および配置のためのオートメーション インターフェイスを提供します (管理ポータルによって内部で使用されます)。これらの API へのアクセスは、管理証明書を使用して制限されます。

 

サービス 既定の制限

クラウド サービス

20

ストレージ アカウント

5

コア

20

SQL データベースの論理サーバー

5

クラウド サービス

Windows Azure クラウド サービス (以前のホステッド サービス) は、配置および拡張の基本単位です。各クラウド サービスは、一連のロールを含む 2 つの配置 (運用とステージング) で構成されます。クラウド サービスには、運用配置のパブリック DNS エントリ (servicename.cloudapp.net という形式) とステージング配置の DNS エントリ (someguid.cloudapp.net という形式) があります。

各配置に 1 つ以上のロール (Web ロールまたはワーカー ロール) が含まれており、各ロールに 1 つ以上のインスタンス (非永続的な VM) が含まれています。各インスタンスには、そのロールのソフトウェア パッケージの非永続的なスナップショットが含まれています。このスナップショットはすべてのインスタンスで同一で、変更することはできません (したがって、特定のロールのすべてのインスタンスに同じビルドが配置されます)。これらのインスタンスでは、Windows Azure 専用バージョンの Windows Server (セキュリティを強化するために多くのサービスが既定で無効になっている、Windows Azure のネットワーク ファブリックやサービス ファブリックで適切に機能するように構成されているなどの違いがあります) が実行され、既定では、Windows Azure ファブリックによって自動的に修正プログラムが適用されます。ライブ修復は、後ほど説明するローリング アップグレードの設定によって処理されます。

クラウド サービスは、任意の Windows Azure データ センターに直接 (サービスを作成するときに配置先の地域を選択します) またはアフィニティ グループを介して配置できます。アフィニティ グループとは、配置先への間接参照です。これにより、アプリケーションのすべてのコンポーネントを同じデータ センターに効率的に配置できます。

Web ロールは、アプリケーション コードをホストする IIS インスタンスを使用してあらかじめ構成されています。ワーカー ロールでホストされるアプリケーション コードは、あらかじめ構成されている実行時間の長いアプリケーションのホストで実行されます。各クラウド サービスは、最大 25 のロールを持つことができます。ロールは、既定では .NET コードを実行するように構成されていますが、Windows Server と互換性のある任意のコード (Java、Python、Ruby、node.js など) を実行するように構成できます。このドキュメントで言及されているプラットフォーム機能はすべて、どのプラットフォームからでも使用できますが、REST ベースの API を対象にする場合は、追加でクライアント プロキシの開発が必要になることがあります。

クラウド サービス内では、すべてのインスタンスにプライベート IP アドレス (10.x ブロックのアドレス) が割り当てられます。ネットワーク アドレス変換により、すべての発信接続が単一の仮想 IP アドレス (VIP) からの接続に見えます (クラウド サービスの配置の VIP)。すべての着信接続は、構成されたエンドポイントを通過する必要があります。これらのエンドポイントにより、内部のロールおよびポートへの負荷分散アクセスが提供されます。たとえば、既定では、クラウド サービスの配置に対する着信 HTTP/HTTPS (ポート 80 および 443) 接続の負荷は、プライマリ Web ロールのすべての使用可能なインスタンスに分散されます。

オンプレミス環境に比べてサービス間の待機時間 (一方のクラウド サービスから NAT とロード バランサーを経てもう一方のクラウド サービスに至るまでの時間) の変動がはるかに大きくなることに注意してください。これは、バッチ処理された ("chunky" な) サービス間接続がスケーラビリティのために推奨される理由の 1 つです。

Windows Azure ファブリックには、クラウド サービスの配置のすべてのインスタンスで使用できる構成サービスも用意されています。必要な構成キーの静的セットが (開発サイクルの一部として) サービス定義で指定され、サービスが Windows Azure にパブリッシュされるときに構成値の初期セットが一緒に配置されます。この構成値のセットは、サービスの配置のすべてのインスタンスからランタイム参照として使用できます。REST インターフェイス、Windows Azure ポータル、または PowerShell スクリプトを使用して実行時に変更することもできます。

実行時構成が変更された場合、すべてのインスタンスで構成変更通知を (アプリケーション コードで) フックして構成の更新を内部で処理することができます。アプリケーション コードが構成変更イベントをキャプチャするように記述されていない場合は、ロールのすべてのインスタンスで構成を更新するためにローリング再起動が行われます。

各インスタンスの状態は永続的ではありません。Windows Azure の基本イメージ (専用の Windows Server VM) の上の構成では、パフォーマンス カウンターの作成、IIS の設定の調整、依存ソフトウェアのインストールなどのための起動時の構成が必要になります。これらの構成スクリプトは、通常、クラウド サービスの構成で定義されるスタートアップ タスクとして実行されます。

クラウド サービスの内部では、Windows Azure ファブリックにより、RoleEnvironment を通じて、構成、内部 IP アドレス、サービス構成などに関する情報が提供されます。Windows Azure インスタンス上で実行されているすべてのプロセスで、RoleEnvironment の情報にアクセスして、構成を取得したり、ネットワーク トポロジを特定したりできます。Windows Azure Management API を使用してこの情報に外部からアクセスすることもできます。

アップグレード ドメインと障害ドメイン

Windows Azure ファブリックには、コンポーネントの障害、再構成、およびアップグレード/修正を管理するための中心的な概念が 2 つあります。それが、アップグレード ドメインと障害ドメインです。

アップグレード ドメインは、Windows Azure サービス内の論理グループです。既定では、各サービスに 5 つのアップグレード ドメインがあります (この値はクラウド サービス定義で変更できます)。サービスの変更やアップグレードは、一度に 1 つのアップグレード ドメインのみに影響します。たとえば、OS への修正プログラムの適用、仮想マシンのサイズの変更、実行中のサービスへのロールまたはロール インスタンスの追加、エンドポイント構成の変更などが対象になります。

これにより、可用性を維持しながら、実行中のクラウド サービスをその場で再構成できます。インスタンスが 1 つしか含まれていないロールでは、アップグレード操作中の可用性が提供されません。単一インスタンスのロールの実行が Windows Azure の SLA を満たさないのはそのためです。

障害ドメインは、基になるハードウェアに基づく論理グループです。この論理グループは、特定のハードウェア構成に直接マップされる保証はありませんが、単一障害点となる基になるリソース (基になる単一の物理サーバー、ラックなど) からインスタンスを自動的に分離するための Windows Azure ファブリックの方法と考えることができます。Windows Azure でサービスの SLA を満たすためには、少なくとも 2 つの障害ドメインにインスタンスを配置する必要があります。これは、単一インスタンスのロールの配置が Windows Azure の SLA を満たさないもう一つの理由です。

概要

以上をまとめると、次のようになります。

  • Windows Azure の配置と拡張の基本単位は、一連のロールで構成されるクラウド サービスです。各ロールには、クラウド用に構成された専用バージョンの Windows Server を実行する、一連の同一のロール インスタンスが含まれています。

  • クラウド サービスでは、物理的なトポロジ (ロールとインスタンス) とアプリケーション コードに加えて、サービス全体の構成を定義します。この構成は実行時に更新できます。

  • 各ロール インスタンスは非永続的です (再起動、修正プログラムの適用、エラー イベントなどが発生した場合、変更やファイルなどが保持される保証はありません)。

  • 各クラウド サービスは、着信および発信の両方のトラフィックに対して単一の仮想 IP を公開します。また、クラウド サービスは、内部のロールおよびポートに対する (ラウンド ロビンの) 負荷分散を提供するエンドポイントを公開します。

  • Windows Azure は、アップグレード ドメインを使用して、インスタンスのグループを論理的に分離します。これにより、ローリング アップグレード/変更が (可用性を維持しながら) 実現されます。

  • Windows Azure は、障害ドメインを使用して、インスタンスを物理的にグループ化して単一障害点から分離します (すべてのインスタンスが同じ基になる物理コンピューターで実行される場合など)。

  • 複数のサブスクリプションを活用して、開発、テスト、ステージング、および運用の環境を分離します。

コンピューティング (ロール インスタンス)

各ロールには、1 つ以上のインスタンスのセットが含まれています。これらのインスタンスは、特殊なバージョンの Windows Server を実行する VM です。インスタンス (VM) には、現在 5 つのサイズがあります (ExtraSmall から ExtraLarge まで)。サイズごとに、割り当てられる CPU、メモリ、ストレージ、および帯域幅が決まっています。

 

仮想マシンのサイズ CPU コア メモリ Web ロールとワーカー ロールのローカル ストレージ リソースのディスク領域 VM ロールのローカル ストレージ リソースのディスク領域 割り当てられる帯域幅 (Mbps)

ExtraSmall

共有

768 MB

19,480 MB

(6,144 MB はシステム ファイル用に予約されています)

20 GB

5

Small

1

1.75 GB

229,400 MB

(6,144 MB はシステム ファイル用に予約されています)

165 GB

100

Medium

2

3.5 GB

500,760 MB

(6,144 MB はシステム ファイル用に予約されています)

340 GB

200

Large

4

7 GB

1,023,000 MB

(6,144 MB はシステム ファイル用に予約されています)

850 GB

400

ExtraLarge

8

14 GB

2,087,960 MB

(6,144 MB はシステム ファイル用に予約されています)

1890 GB

800

複数のインスタンスが異なる障害ドメインとアップグレード ドメインに配置されている場合に Windows Azure でクラウド サービスに対して提供される SLA は次のとおりです。

  • インターネットに直接接続されたロール (外部エンドポイントを持つロール) の外部接続で 99.95% の可用性

  • ロール インスタンスの問題の 99.9% を 2 分以内に検出して修正措置を開始

実行中のアプリケーションで、ロール インスタンスのサイズと数の両方を動的に変更できます (ロール インスタンスのサイズを変更するとローリング再配置がトリガーされます)。Windows Azure アプリケーションはスケールアウト アプローチで作成されるため、インスタンスのサイズの選択においては、必ずしも大は小を兼ねるとは言えません。これは、コスト (使用しないものにもコストがかかります) とパフォーマンス (ワークロードが CPU バウンドか I/O バウンドかなどによります) の両方に当てはまります。インスタンスの数とサイズを選択するための方法については、このドキュメントの「ベスト プラクティス」で詳しく説明します。

ストレージ

Windows Azure ストレージは、BLOB (ファイル)、キュー、およびテーブル ストレージ (値のキー) を提供する Windows Azure の基本永続データ サービスです。ストレージ アカウントは、拡張と可用性の基本単位で、以下の機能を提供します。ストレージ サービスとのすべての通信は、HTTP 上の REST インターフェイスに基づいています。

 

ストレージ アカウントの制限 上限

記憶域容量

100 TB

操作 (トランザクション)

5,000/秒

帯域幅

3 Gbps

Availability

99.9%

応答の調整

HTTP 503 (サーバーがビジー状態)

Windows Azure ストレージの可用性の SLA では、99.9% 以上の時間で、データの追加、更新、読み取り、および削除に対する正しい形式の要求が正常に処理され、ストレージ アカウントがインターネット ゲートウェイに接続できることが保証されます。

これらの制限は、個々のストレージ アカウントが使用するすべてのストレージの間で共有されます。したがって、1 秒あたりの操作の数と全体的な帯域幅は、テーブル、BLOB、およびキューの間で共有されます。アプリケーションで 1 秒あたりの操作の合計数が上限を超えると、サービスから HTTP コード 503 (サーバーがビジー状態) が返されます。操作はストレージの各側面 (テーブル、キュー、または BLOB) に固有です。詳細についてはこの後のサブセクションで説明します。

前に使った運送用コンテナーのたとえで言うと、各ストレージ アカウントは、容量が決まっているコンテナーです。1 つのアカウント (運送用コンテナー) では足りない場合は、同じアプリケーションで複数のアカウントを使用する必要があります。

Windows Azure ストレージでは、可用性と回復力が既定で提供されます。Windows Azure ストレージに対するすべての書き込みや更新は、3 つのストレージ ノード (それぞれ異なるアップグレード ドメインと障害ドメインに配置されています) に透過的に、一貫性のある形でレプリケートされます。Windows Azure ストレージへのアクセスは、アクセス キーの形式の単一要素認証を使用して制御されます。各ストレージ アカウントに主キーとセカンダリ キーがあるため、主キーがローテーションされているときにも可用性が維持されます。Windows Azure ストレージのデータは、"ミラー" データ センターに自動的に地理分散されます (ポータルを使用してこの機能を無効にしていない場合)。地理分散は不透明で、プライマリ データ センターで障害が発生すると、DNS リダイレクトを活用してクライアントをセカンダリの場所にフェールオーバーします。

Windows Azure ストレージでは、自動レプリカによってデータの回復力が提供されますが、アプリケーション コードで (または開発者やユーザーによって) データが誤って (意図せず) 削除されたり更新されたりした場合のデータの破損を防ぐことはできません。アプリケーション エラーやユーザー エラーが発生した場合にデータの忠実性を維持するには、より高度なテクニックを使用する必要があります (データを監査ログと共にセカンダリ ストレージにコピーするなど)。BLOB ストレージには、BLOB のコンテンツの特定の時点の読み取り専用スナップショットを作成できるスナップショット機能が用意されています。この機能を、BLOB のデータ忠実性ソリューションの基盤として使用できます。

Windows Azure ストレージでは、ストレージ分析機能による遠隔測定が提供されます。これにより、テーブル、キュー、および BLOB に対する個々のストレージ呼び出しに関する使用状況データが収集および公開されます。収集ポリシー (すべてのデータを収集、テーブルのデータのみを収集など) と保有ポリシー (データを保持する期間) を使用して、各ストレージ アカウントでストレージ分析を有効にする必要があります。

BLOB

BLOB ストレージは、Windows Azure のファイル管理サービスを提供します。これにより、大量の非構造化データを、可用性の高い経済的な方法で格納できます。次の 2 種類の BLOB が用意されています。

  • ブロック BLOB。ブロック BLOB は、大きな BLOB データを効率的に管理できるように設計されています。各ブロック BLOB は最大 50,000 個のブロックで構成され、各ブロックの最大サイズは 4 MB です (ブロック BLOB 全体の最大サイズは 200 GB です)。ブロック BLOB では並列アップロードがサポートされているため、複数の大きなファイルを効率的な形で同時にネットワーク経由で移動できます。個々のブロックは、挿入、置換、削除することはできますが、その場で編集することはできません。

  • ページ BLOB。ページ BLOB は、ランダムな読み取り/書き込み操作 (VHD へのアクセスなど) を効率的に提供できるように設計されています。512 バイトのページで構成され、最大サイズは 1 TB です。個々のページやページのグループを追加したり更新したりできます (その場で上書きできます)。

BLOB ストレージの設計上の制限を次の表に示します。これらの操作はすべてストレージ アカウント全体の制限に対してカウントされることに注意してください。

 

BLOB のカテゴリ 上限

BLOB の最大サイズ (ブロック)

200 GB (5 万ブロック)

ブロックの最大サイズ

4 MB

BLOB の最大サイズ (ページ)

1 TB

ページ サイズ

512 バイト

最大帯域幅/BLOB

480 Mbps

アプリケーションで 1 つの BLOB のサイズまたは帯域幅の上限を超えた場合は、複数の BLOB ファイルに同時に (または順番に) 書き込みを行うことができます。1 つのストレージ アカウントの上限を超えた場合は、複数のストレージ アカウントを使用して容量を追加できます。

キュー

Windows Azure キューは、パブリッシャーとサブスクライバーの間の仲介型メッセージング サービスを提供します。複数のパブリッシャーとサブスクライバーを同時にサポートできますが、pub/sub、トピック ベースのルーティングなどの高次のメッセージング プリミティブはネイティブで公開されません。通常は、一連のワーカー ロール インスタンスに (または複数のホステッド サービスなどの間で) 作業項目 (メッセージ、ドキュメント、タスクなど) を分散するために使用されます。

Windows Azure Queues

キューのメッセージは、アプリケーションによって取得および削除されない場合、7 日後に自動的に削除されます。キューのメッセージにより、情報のパブリッシャーとコンシューマーの分離が実現されます。両方の側でストレージ アカウント キーとキュー名がわかっていれば互いに通信できます。

 

キューのカテゴリ 上限

キューのメッセージの最大数

該当なし (ストレージ アカウントの上限まで)

メッセージの最大有効期間

1 週間 (自動的に削除されるまで)

最大メッセージ サイズ

64 KB

最大スループット

約 500 メッセージ/秒

キューは、生データではなく制御メッセージの受け渡しを目的としています。メッセージが大きすぎてキューに収まらない場合は、メッセージをリファクターしてデータとコマンドに分離します。データは BLOB ストレージに格納し、データの参照 (URI) と目的 (BLOB ストレージのデータをどうするか) をキューのメッセージに格納します。

1 つのキューのスループットを向上させるには、複数のメッセージを 1 つのメッセージとしてバッチ処理して、そのメッセージのタスクの進行状況を Update Message コマンドで追跡します。または、複数のメッセージを BLOB に格納して、その BLOB へのポインターをキューのメッセージに格納します。

1 つのキューによって提供されるスループットでは足りない場合は、複数のキューを同時に使用します。その場合は、アプリケーションに適切なパーティション分割とルーティング ロジックを実装する必要があります。

テーブル

Windows Azure テーブル ストレージは、列形式 (2 次元) のデータの、高度に永続的でスケーラブルな、一貫性のあるデータ ストアを提供します。次の図に示すように、{ パーティション キー, 行キー } -> { data[] } セマンティクスを使用してデータを格納したりデータにアクセスしたりできます。各テーブルはパーティションによって分割され、各パーティションにエンティティが含まれます。各エンティティには、独自の (フラット) スキーマ (プロパティ (列) の一覧) を指定できます。

Windows Azure テーブル

各パーティションでは毎秒 500 までの操作がサポートされ、各テーブルでは、ストレージ アカウントで実行できる最大数までの操作がサポートされます。各エンティティには、実際のデータだけでなく列のメタデータも含まれるため (すべてのエンティティに異なるスキーマを指定できるため)、長い列名を使用することは (大規模なアプローチでは特に) お勧めしません。

 

テーブルのカテゴリ 上限

1 秒あたりの操作の最大数/パーティション

500

エンティティの最大サイズ (列名 + データ)

1 MB

列の最大サイズ (byte[] または string)

64 KB

[最大行数]

該当なし (ストレージ アカウントの上限まで)

サポートされるデータ型

byte[]、Boolean、datetime、double、Guid、int32、int64、string

個々のエンティティ (行と考えることができます) の最大サイズは 1 MB で、個々の列のサイズの上限は 64 KB です。サポートされているデータ型は上の表のとおりです。サポートされていないデータ型 (DateTimeOffset など) を使用する場合は、アプリケーションのコードにシリアル化プロキシが必要になります (DateTimeOffset を標準の文字列の形式で格納するなど)。

テーブル ストレージに格納されているデータにアクセスするには、パーティションとエンティティに関連付けられているキーを使用するか、パーティションまたはエンティティのスキャンを使用します。フィルター式をクエリの一部としてプッシュしてテーブル ストレージで実行できるため、フィルター プロジェクションがサポートされます。テーブル ストレージにはセカンダリ インデックスがないため、パーティション キーまたはエンティティ キーに基づかない参照では、テーブルやパーティションのスキャンを実行する必要があります。これは、一般に、パーティションに含まれているエンティティが多い場合はパフォーマンスに大きく影響します。

クエリの処理が 5 秒以内に終わらない場合は、継続トークンが返されます。これにより、アプリケーションでクエリの結果を受信し続けることができます。クエリで取得されるエンティティの数が 1,000 を超える場合は、ページング モデルを活用して、データを 1,000 エンティティごとのチャンクで返す必要があります (テーブル ストレージの API でネイティブでサポートされています)。

現在テーブル ストレージでサポートされているクエリ式は、フィルターと選択 (特定のプロパティの選択) だけです。テーブル ストレージでは、サーバー側の集計やグループ化のセマンティクスはサポートされていません。豊富な集計機能や分析機能を必要とするアプリケーションを作成する場合は、集計された形式でデータを格納するか、Windows Azure SQL データベースなどのリレーショナル エンジンを使用することをお勧めします。テーブル ストレージのデータを補助 SQL データベースで集計してクエリやレポートに使用するハイブリッド アプローチを採用しているアプリケーションもあります。

テーブル ストレージを効率的かつ効果的に使用するためには、適切なパーティション関数を選択することが重要です。パーティション関数には主に次の 2 つの種類があります。

  • 時間。時間に基づくパーティション関数は、Windows Azure 診断のパフォーマンス カウンターなどの時系列データを格納するためによく使用されます (この使用方法については、このドキュメントの遠隔測定のセクションで説明します)。これらのパーティション関数は、現在の時刻を、時間枠を表す値 (現在の分、時間など) に変換します。

    これらのパーティション関数は、特定のパーティションを効率的に参照および検出できますが (テーブル ストレージのフィルター句では >=、<= などがサポートされているため)、選択した時間枠が小さすぎる場合にスパイク イベントが発生すると調整が行われる傾向があります。たとえば、選択したパーティション関数が現在の分の場合にスパイク イベントが発生すると、多数のクライアントが同じパーティションに同時に書き込みを行おうとする可能性があります。これは、挿入のスループットだけでなくクエリのスループットにも影響します。

  • データ。データ中心のパーティション関数は、格納 (または取得) するデータの 1 つ以上のプロパティに基づいてパーティションの値を計算します。適切なデータ ドリブンのパーティション関数の選択は、クエリ パターン、パーティション キーの密度 (最終的にパーティションに配置されるエンティティの数)、予期しない成長 (きわめて大きなテーブルを再度均衡化させるのは必ずしも容易な作業ではありません) など、いくつかの要因に依存します。一般的なパターンは次のとおりです。

    • 単一フィールド。パーティション キーは、ソース データの 1 つのフィールドです (注文情報の顧客 ID など)。

    • 複数のフィールド。パーティション キーまたは行キーが、ソース データの複数のフィールドの組み合わせ (通常は連結) です。パーティション キーを選択するときには、バッチ操作ではすべてのエンティティが同じパーティションに存在する (同じパーティション キーを持つ) 必要があることに注意してください。

    • 計算フィールド。パーティション キーは、決定的関数に基づいて 1 つまたは複数のフィールドから計算されます。たとえば、ユーザー プロファイルを複数のパーティションに分散する場合などがこれに当たります。比較的均一な分布のためのハッシュ関数を使用してユーザー ID をハッシュし、目的のパーティションの数の剰余を取ります。

すべての重要なアプリケーションで複数のパーティションを使用する必要があります。エンティティの合計数が少ないテーブルでも (200 個など)、アプリケーションで 1 秒間に実行される要求の数が数千に及ぶ場合は、スループットのために複数のパーティションが必要です。

  • 1 つのテーブル / 1 つのパーティション。最も単純なオプションです (パーティション キーの値が一定)。データの量が限られていて、要求のスループットの要件も高くない (< 500 エンティティ/秒)、小規模なワークロードに適しています。

  • 1 つのテーブル / 複数のパーティション。ほとんどの配置で一般的なオプションです。対象のクエリ パターンに合うように慎重にパーティション キーを選択します。

  • 複数のストレージ アカウント / 複数のパーティション。予想される負荷が 5,000 操作/秒を超える場合は、複数のストレージ アカウントに分散されたテーブルを使用する必要があります。

データを後から再度均衡化させる (再分割する) 場合は、新しいパーティション キーを使用してすべてのエンティティを読み取ってコピーしてから古いデータを削除する必要があるため、コストが高くなります。パーティションのサイズに下限はありません。パーティションを 1 つのエンティティ (行) で構成することもできます。

1 つのテーブルによって提供されるスループットでは (パーティションを慎重に選択しても) 足りない場合は、異なるストレージ アカウントの複数のテーブルを同時に使用します。その場合は、適切なストレージ アカウントを選択するために適切なルーティング ロジックをアプリケーションに実装する必要があります。

コンテンツ配信ネットワーク (CDN)

Windows Azure コンテンツ配信ネットワーク (CDN) を使用すると、世界中に分散されたキャッシュ ネットワークで (BLOB またはアプリケーションの出力からの) 静的なコンテンツを効率的にキャッシュすることができます。これにより、静的なコンテンツの配信に関するアプリケーションの負荷を軽減し、全体的なエンド ユーザー エクスペリエンスを向上させることができます。

コンテンツ配信ネットワークの可用性の SLA では、キャッシュされたオブジェクトの配信について 99.9% の可用性 (月単位) が保証されています。

CDN を使用するには、この機能がサブスクリプションでアクティブになっている必要があります。そこから、BLOB のコンテンツ (一般に公開されているコンテナーや匿名アクセス コンテナーのコンテンツ) や匿名のアプリケーション出力のコンテンツ (例: http://www.myapp.com/cdn/somepage.aspx) をキャッシュすることができます。

一般に、大規模なアプリケーションでは、よくアクセスされるすべての静的なコンテンツ (画像、css など) を、適切なキャッシュの有効期限ポリシーを使用して CDN で配信する必要があります。

たとえば、100 万タイトルの書籍を扱う電子書籍のオンライン ストアがあったとします。この場合、すべてのタイトルのコンテンツ (画像など) を CDN に含めるとコストが高くなりすぎますが (ほとんどのコンテンツは頻繁にアクセスされず、絶えず期限切れになるため)、よく利用されるコンテンツのみを含めると (上位 50 タイトルのみを含めるなど)、キャッシュのコスト バランスを適正化できます。

Windows Azure Diagnostics

大規模なサービスの提供を成功させるための重要な要素の 1 つが遠隔測定 (アプリケーションの操作、パフォーマンス、およびエンド ユーザー エクスペリエンスに対する洞察) です。Windows Azure アプリケーションで遠隔測定を活用する際には、スケールアウトと分散というこのプラットフォームの特性と、遠隔測定の収集、分析、および利用のために使用できるプラットフォーム サービスを考慮に入れる必要があります。

Windows Azure で遠隔測定を収集して理解するための基本テクノロジ コンポーネントとなるのが Windows Azure 診断 (WAD) です。WAD は、個々のインスタンスからデータを収集して中央の収集ポイント (ストレージ アカウント) に転送するエージェントと、データの格納およびアクセスのための一連の標準的な構造と規則で構成されています。エージェントでは、コード (.NET)、配置されたプロジェクト コードに埋め込まれた構成ファイル、BLOB ストレージに配置された、集中管理されている構成ファイルなど、数多くの構成方法がサポートされています。さらに、構成の一部は動的で、更新された診断ファイルを BLOB ストレージにプッシュして、対象のエージェントにプルすることができます。

Windows Azure 診断

WAD の構成はさまざまなデータ ソースに対応しています。それらのデータ ソースがそれぞれ定期的に収集され、Event Tracing for Windows (ETW) セッションによってバッチ処理されて、対象のストレージ アカウントにパブリッシュされます。エージェントは、一時的な接続の問題や再試行などに対処します。使用可能なデータ ソースは次のとおりです。

  • パフォーマンス カウンター。パフォーマンス カウンターの値のサブセット (CPU、メモリなど)。ローカル ETW セッションにキャプチャされて、定期的にテーブル ストレージにステージングされます。

  • Windows イベント ログ。Windows イベントの記録のサブセット (アプリケーション、システムなど)。ローカル ETW セッションにキャプチャされて、定期的にテーブル ストレージにステージングされます。

  • Windows Azure のログ。アプリケーション コードによって (System.Diagnostics.Trace を使用して) パブリッシュされ、DiagnosticMonitorTraceListener トレース リスナーによってキャプチャされるアプリケーション ログ (トレース メッセージ)。これらは、対象のストレージ アカウントの WAD パフォーマンス カウンター テーブルにパブリッシュされます。

  • IIS 7.0 のログ。IIS によって記録される、要求に関する標準の IIS ログ情報 (Web ロールのみ)。ローカル ファイルに収集され、定期的に BLOB ストレージにステージングされます。

  • IIS の失敗した要求ログ。失敗した要求に関する IIS の情報。ローカル ファイルに収集され、定期的に BLOB ストレージにステージングされます。

  • クラッシュ ダンプ。システム障害が発生した場合、オペレーティング システムの状態に関するログがキャプチャされて、BLOB ストレージにパブリッシュされます。

  • データ ソース。WAD では、追加のローカル ディレクトリ (ローカル ストレージのログ ディレクトリなど) を監視して、データを定期的に BLOB ストレージのカスタム コンテナーにコピーできます。

これらのデータ ソースは、収集するデータのサブセット (パフォーマンス カウンターのリストなど) と、収集/パブリッシュの間隔を使用して構成されます。実行時構成を変更したり、エージェントから対象のストレージ アカウントにデータをすぐにパブリッシュしたりするために使用できる PowerShell スクリプトも用意されています。

Important重要
遠隔測定は別のストレージ アカウントに記録してください。遠隔測定とアプリケーション データのログを同じストレージ アカウントに記録すると、重大な競合の問題が大規模に発生します。

SQL データベース

Windows Azure SQL データベースは、サービスとしてのデータベースを提供します。これにより、リレーショナル データベースのプロビジョニング、データの挿入、およびクエリをアプリケーションで迅速に行うことができます。使い慣れた SQL Server の機能の多くが提供される一方で、ハードウェア、構成、修正、および回復力に関する負担は取り除かれます。

note
SQL データベースは、SQL Server と 1:1 で対応する機能を提供するものではありません。クラウド アプリケーションに固有の、一連の異なる要件 (柔軟な拡張、メンテナンス コストを削減するサービスとしてのデータベースなど) を満たすことを目的としています。詳細については、http://blogs.msdn.com/b/windowsazure/archive/2012/06/26/data-series-sql-server-in-windows-azure-virtual-machine-vs-sql-database.aspx を参照してください。

このサービスは、汎用的なハードウェアで構築されたインフラストラクチャで複数のユーザーおよびサブスクリプションのデータベースが実行されるマルチテナント共有環境で実行されます (スケールアップではなくスケールアウト)。

データベースは論理サーバー内でプロビジョニングされ、各論理サーバーに既定で最大 150 のデータベースが含まれます (master データベースを含む)。既定では、各サブスクリプションで 5 つの論理サーバーをプロビジョニングできます。このクォータ (および論理サーバーごとのデータベースの最大数) は、サポートに連絡することによって増やすことができます。

生成された固有のパブリック DNS 名 ([servername].database.windows.net という形式) が各論理サーバーに割り当てられ、サブスクリプションのすべての論理サーバーが同じパブリック IP アドレスを共有します。論理サーバー (およびデータベース) には標準の SQL ポート (TCP/1433) でアクセスし、REST ベースの管理 API にはポート TCP/833 でアクセスします。

論理サーバー (およびそのすべてのデータベース) へのアクセスは、既定では Windows Azure Management Portal に対する IP ベースのファイアウォール ルールによって制限されます (論理サーバーや個々のデータベースに対してルールを設定することもできます)。Windows Azure アプリケーションにアクセスできるようにしたり、Windows Azure の外部から直接アプリケーションに接続できるようにしたりするには (SQL Server Management Studio を接続する場合など)、ファイアウォール ルールを構成する必要があります。これらのルールは、Windows Azure Management Portal から Management Service API 呼び出しを使用して構成できます。

SQL データベースでは、SQL Server の主な機能の多くがサポートされていますが、いくつかの重要な例外があります。以下はその例です。

  • すべてのテーブルにクラスター化インデックスが含まれている必要があります。クラスター化インデックスが定義されていない SQL データベースのテーブルにデータを挿入することはできません。

  • 共通言語ランタイム (CLR) のサポート、データベース ミラーリング、Service Broker、データ圧縮、およびテーブル パーティション分割は組み込まれていません。

  • XML インデックスはサポートされていません (XML データ型はサポートされています)。

  • 透過的なデータ暗号化 (TDE) およびデータ監査はサポートされていません。

  • フルテキスト検索はサポートされていません。

各データベースの作成時にサイズの上限を構成します。現在使用可能なサイズの上限は、1 GB、5 GB、10 GB、20 GB、30 GB、40 GB、50 GB、100 GB、および 150 GB (現在使用可能な最大サイズ) です。データベースのサイズが上限に達すると、INSERT コマンドや UPDATE コマンドが拒否されるようになります (データのクエリと削除は引き続き実行できます)。ALTER DATABASE コマンドを実行してデータベースのサイズを変更 (増減) することもできます。

データベースは 1 日あたりの平均使用サイズに基づいて課金されるため、急速な拡大や予想外の拡大が見込まれるアプリケーションでは、データベースの最大サイズを最初に 150 GB に設定できます。データベースを 150 GB を超えて拡張するには、スケールアウト アプローチを利用する必要があります。詳細についてはこの後のセクションで説明します。

SQL データベースには、ノード レベルのエラーに対する回復力が組み込まれています。データベースに対するすべての書き込みは、クォーラム コミットの手法を使用して複数のバックグラウンド ノードに自動的にレプリケートされます (トランザクションが成功と見なされて終了するためには、プライマリと少なくとも 1 つのセカンダリでアクティビティがトランザクション ログに書き込まれたことが確認される必要があります)。ノードでエラーが発生した場合は、データベースがいずれかのセカンダリ レプリカに自動的にフェールオーバーします。これにより、クライアント アプリケーションで一時的な接続の中断が発生します。すべての SQL データベース クライアントで一時的な接続の処理を実装する必要があるのは主にこのためです (一時的な接続の処理の実装については後ほど説明します)。

月単位の可用性の SLA で 99.9% のアップタイム (5 分間隔で 30 秒以内に SQL データベースに接続できる状態として定義されています) が保証されています。前の段落で説明したフェールオーバー イベントが通常 30 秒以内に発生するため、アプリケーションで一時的な接続エラーを処理する必要があります。

SQL データベースでは、状態とパフォーマンスを動的管理ビュー (DMV) で確認できます。これらの DMV には、システムの主な側面に関する情報が含まれています (クエリ パフォーマンス、データベースとテーブルのサイズなど)。アプリケーションで主要な DMV の情報を定期的に収集して分析し、遠隔測定と検証のより広範なフレームワークに統合する必要があります。

SQL データベースでは、いくつかのビジネス継続性 (バックアップ、復元) オプションを使用できます。データベースは、データベース コピー機能または DAC インポート/エクスポート サービスを使用してコピーできます。データベース コピーではトランザクションの一貫性が確保されますが、bacpac (インポート/エクスポート サービスを使用) では確保されません。これらのオプションはどちらも、データ センター内のキューに基づくサービスとして実行されます。現時点では、完了に要する時間の SLA は提供されていません。

データベース コピーとインポート/エクスポート サービスでは、ソース データベースの負荷がかなり高くなるため、リソースの競合や調整イベントが発生する可能性があります (この後の「共有リソースと調整」で説明します)。これらの方法では、SQL Server でサポートされているレベルの増分バックアップは利用できませんが、特定の時点への復元を実現する新機能があります (現在はプレビュー)。この機能を使用すると、データベースを過去 2 週間以内の任意の時点に復元することができます。

現在サポートされている認証方法は SQL 認証だけです (データベースに登録されているユーザーのユーザー名/パスワードに基づく単一要素のログイン)。Active Directory 認証や 2 要素認証はまだ使用できません。ADO.NET、ODBC などの組み込みの暗号化サポートを使用して SQL データベースへの接続を暗号化することを強くお勧めします。データベース レベルの権限は、SQL Server と一貫性があります。Windows Azure SQL データベースのセキュリティの設定の詳細については、「Windows Azure SQL データベースにおけるデータベースとログインの管理」を参照してください。

SQL データベースには、クエリ パフォーマンスとデータベースの状態を監視するための動的管理ビューが豊富に用意されていますが、そのデータを収集して分析するための自動化されたインフラストラクチャは用意されていません (直接アタッチされるプロファイラーや OS レベルのパフォーマンス カウンターなどのおなじみのツールは使用できません)。収集と分析の方法については、このドキュメントの遠隔測定に関するセクションで説明します。

共有リソースと調整

SQL データベースは、既に説明したように、共有インフラストラクチャで実行されるマルチテナント サービスです。異なるテナントのデータベースが、汎用的なハードウェアに基づいて構築された基になる物理ノードを共有します。システム内の他のユーザーが、同じ基になるインフラストラクチャの主要なリソース (ワーカー スレッド、トランザクション ログ、I/O など) を使用できます。リソース使用量は管理されており、データベースがあらかじめ設定されたリソースの制限を超えることはありません。テナントまたは物理ノードのレベルでこれらの制限を超えると、SQL データベースで使用の調整が行われるか、接続が解除されます。これらの制限を次の表に示します。

 

リソース トランザクション/セッションあたりの最大値 物理ノードあたりの最大値 ソフト調整の制限 ハード調整の制限

ワーカー スレッド

該当なし

512

305

410

データベース サイズ

構成された最大サイズ (データベースあたりの上限は 150 GB)

該当なし

なし

100% (制限に達すると挿入や更新が受け入れられなくなります)

トランザクション ログの増加

2 GB (トランザクションあたり)

500 GB

該当なし

該当なし

トランザクション ログの長さ

全ログ領域の 20% (100 GB)

500 GB

該当なし

該当なし

ロック数

100 万 (トランザクションあたり)

該当なし

該当なし

該当なし

システム タスクのブロック

20 秒

該当なし

該当なし

該当なし

一時データベース領域

5 GB

該当なし

該当なし

5 GB

メモリ

該当なし

該当なし

該当なし

16 MB (20 秒間)

同時要求の最大数

400 (データベースあたり)

該当なし

該当なし

該当なし

トランザクションの上限に達すると、トランザクションが取り消されます。データベースがソフト調整の制限に達すると、トランザクションと接続が減速するか中止されます。ハード調整の制限に達すると、基になる物理ノードのすべてのデータベース (およびユーザー) に影響が及び、既存の操作は中止され、新しい操作や接続は、リソースが調整のしきい値を下回るまで拒否されます。

これらの調整の制限が、アプリケーションの設計やパフォーマンスの非直感的な制限となる場合があります。たとえば、トランザクション ログの増加が 2 GB まで (トランザクションあたり) に制限されていると、大きなテーブルにインデックスを作成することはできません (インデックスを作成するとトランザクション ログが 2 GB を超える場合)。このような操作を実行するためのテクニックについては、このドキュメントの「ベスト プラクティス」で説明します。

この種の調整状態や一時的なエラーを処理するためには、クライアント コードを慎重に設計および実装する必要があります。また、データベース層をスケールアウトして、複数のデータベースを同時に活用する必要があります (スケールアウトについては次のセクションで説明します)。

SQL クライアント アプリケーション コードの要件を以下に示します。

  • 調整に関連する SQL エラー コードを認識して適切なバックオフ ロジックを提供する再試行コードを実装します。アプリケーションになんらかのバックオフ ロジックがないと、アプリケーションがデータベースにピーク時の負荷を与え続けて、データベースが調整された状態のままになる可能性があります。

  • 一時的な接続、調整、およびハード障害 (構文エラー、ストアド プロシージャが見つからないなど) を区別する再試行コードを使用して、調整エラーをログに記録します。これは、アプリケーションの可用性の問題の追跡とトラブルシューティングに役立ちます。

  • 遮断器のパターンを実装します。適切に選択した再試行ポリシーが期限切れになったら (待機時間とシステムの応答に合わせてアプリケーションの再試行の頻度を調整します)、一時的でないエラーを処理するコード パスを開始して (遮断機を切る)、アプリケーション コードで以下の処理を実行します。

    • 別のサービスや方法にフォールバックします。アプリケーションで新しいデータを SQL データベースに挿入できなかった場合 (しかも、そのデータをすぐに使用する必要がない場合) は、そのデータを DataTable (またはその他の XML/JSON 形式) にシリアル化して BLOB ストレージのファイルに書き込むことができます。その後、ユーザー (または API 呼び出し) に成功コードを返して、データを後でデータベースに挿入します。

    • そのデータまたはワークフローが省略可能な場合 (エンド ユーザー エクスペリエンスに影響を与えない場合) は、null 値を返してフェイル サイレント動作を適用します。

    • 有効な (適切な) フォールバック メカニズムがない場合は、エラー コードを返してフェイル ファースト動作を適用します。

スケールアウトの実現

SQL データベースでは、多数の比較的小さなスケール単位 (データベース) を簡単に提供できます。Windows Azure で SQL データベースを使用して拡張性の高いアプリケーションを実装するには、スケールアウト アプローチを採用して、変動する需要に対応するために複数のデータベースでリソースを構成する必要があります。従来のアプリケーションは、回復力の高い単一のスケールアップ データベース サーバー ("チタン製の卵の殻") を対象としているため、スケールアウト データベース サービスを効率的に活用するためには入念な設計が必要になります。

SQL データベースでは、その他のコア Windows Azure サービスと同様に、スケールアウトと構成が、スケール (データベース サイズ、スループット) とリソース (ワーカー スレッドなど) を追加するための鍵になります。SQL データベースにパーティション分割/シャーディング (スケールアウト) を実装するには主に次の 2 つの方法があります。これらの方法は、1 つのアプリケーションで同時に使用することもできます。

  • 行方向のパーティション分割。行方向のパーティション分割では、完全なテーブルまたはデータ セットが個別のデータベースに分割されます。たとえば、複数の顧客に対応するマルチテナント アプリケーションで顧客ごとにデータベースを作成したり、大規模なシングルテナント アプリケーションで顧客テーブルを注文テーブルとは別のデータベースに配置したりすることができます。パーティション分割キーはテナント ID (顧客 ID など) であるのが一般的です。下の図では、行方向のパーティション分割によってデータ セットが 3 つの異なるデータベースに分割されています。ここでは、電子メールのハッシュがパーティション値として使用されています (パーティション キーは電子メールです。パーティション関数では、キーのハッシュを使用してデータを対象のデータベースにマップします)。

    行方向のパーティション分割です。
  • 列方向のパーティション分割。列方向のパーティション分割では、データ セットがスキーマのパーティション分割に基づいて複数の物理テーブルまたは物理データベースに分割されます。たとえば、顧客データと注文データを複数の異なる物理データベースに分割できます。下の図では、列方向のパーティション分割によってデータ セットが 2 つの異なるデータベースに分割されています。主要なユーザー情報 (名前、電子メール) は DB1 に格納され、ユーザー プロファイルの情報 (アバター画像の URI など) は DB2 に格納されます。

    列方向のパーティション分割です。

多くのアプリケーションでは、行方向と列方向のパーティション分割の組み合わせ (ハイブリッド パーティション分割) が使用され、その他のストレージ サービスも組み込まれます。たとえば上の例では、ユーザーのアバター画像が、アプリケーションで完全な URL に展開される ID としてデータベースに格納されています。この URL は、BLOB に格納されている画像にマップされます。

スケールアウトされたリレーショナル データ ストアを使用する場合は、可用性の計算がまったく異なります。多数のシャードを含むシステムでは、個々のデータ セグメントがオフラインになる可能性は高まりますが、アプリケーション全体が使用できなくなる可能性は大幅に低下します。したがって、アプリケーションでバックエンドのデータ ストアの部分的な可用性を考慮する必要があります。スケールアウトのデータ モデルでは、データの可用性はオール オア ナッシングの問題ではなくなります。

データの再分割は (データの利用モデルや分布が時間の経過と共に変化する場合は特に) 困難になることがあります。範囲に基づくパーティション分割キーでは、固定数 (パーティション分割値のハッシュの剰余を使用) に基づく場合もパーティション分割値の分布に基づく場合も、シャード間のデータの再均衡化が必要になります。範囲に基づくパーティション構成では、再均衡化の操作を簡素化するためにバイナリ分割/マージがよく使用されます。

たとえば、固定範囲の分割方法 (姓の最初の文字など) では、最初は分布が均衡していても、新しいユーザーが追加されるにつれてすぐに均衡が大きく崩れます (新しいユーザーの姓が均等に分散しているとは限らないため)。時間が経つにつれてパーティション分割のメカニズムを調整する必要が生じる可能性と、データの再均衡化のコストに注意してください。

参照に基づくパーティション構成は、すべてのデータ テナント (パーティション) に高パフォーマンスの参照メカニズムが必要になるため、実装がより困難になります。その一方で、再均衡化の際にテナントを個別に新しいパーティションに移動できるため、細かな再均衡化に向いています。データをコピーせずにシステムに容量 (新しいデータベースなど) を追加することもできます。

共有リレーショナル データベースのスケールアウトに移行する際には、シャーディングの方法の組み合わせに関係なく、いくつかの制限があります。それらの制限により、データ管理とクエリに対するアプローチの変更が必要になります。

  • 従来の SQL データのストレージとクエリでは、データの格納および一貫性のために高度に正規化されたデータ モデルを活用するのが "良い" 設計とされていました。この方法では、グローバルに一貫したデータ領域を想定し、テーブル間の相互参照と JOIN を活用します。物理的に分散したノードにデータが分散されている場合、JOIN と相互参照は、1 つのシャード内でのみ有効です。SQL データベースは複数のデータベースの分散クエリをサポートしていないため、データのマージ、非正規化、およびシャード間のレプリケーションをクライアント層で処理する必要があります。

  • 参照データとメタデータは、通常、参照テーブルで集中管理されます。スケールアウト アプローチでは、これらの参照テーブルを (共通のパーティション分割キーで分割できないすべてのデータと共に) シャード間でレプリケートして一貫性を維持する必要があります。

  • シャード間で拡張性とパフォーマンスに優れた分散トランザクションを提供するための実用的な方法はありません。シャード間ではデータ (およびスキーマの更新) のトランザクション上の一貫性が確保されません。アプリケーション コードでは、シャード間の一貫性があまり厳密でないことを前提とする (考慮に入れる) 必要があります。

  • アプリケーション コードで適切なシャードに接続するにはシャーディング メカニズム (行方向、列方向、パーティション分割の種類) を認識できる必要があります。

  • 一般的な ORM (Entity Framework など) では、スケールアウト データ モデルがネイティブで認識されません。大規模な ORM を多用するアプリケーションでは、行方向のシャーディングとの互換性を確保するために大幅な再設計が必要になる場合があります。列方向のシャーディングでテナント (顧客) を 1 つのデータベースに分離する設計では、一般に、データ アクセス レイヤーで必要な再設計が少なくて済みます。純粋な列方向のシャード モデルには、個々のシャードが 1 つのデータベースの容量によって制限されるという短所があります。

  • 複数のシャードを操作 (読み取りまたは書き込み) する必要があるクエリは、スキャッター/ギャザー パターンを使用して実装する必要があります。これにより、個々のクエリが複数のシャードに対して実行され、クライアントのデータ アクセス レイヤーで結果セットが集計されます。

SQL データベースのスケールアウトは、データを複数の SQL の間で手動でパーティション分割 (シャーディング) して行われます。このスケールアウト アプローチでは、スケールに対して線形に近い形で増加するコストを実現できます。柔軟な増加 (キャパシティ オン デマンド) により、容量とコストを必要に応じて増やすことができます。すべてのアプリケーションが大幅な再設計なしでこのスケールアウト モデルをサポートできるわけではありません。

  • スキーマの更新で (多数のシャードを更新する場合には特に) トランザクションの一貫性が保証されません。アプリケーションで計画ダウンタイムを受け入れるか、複数のバージョンのスキーマを同時に配置する必要があります。

  • ビジネス継続性プロセス (バックアップ/復元など) で複数のデータ シャードを考慮する必要があります。

これらの課題に対処するための設計上の推奨事項とベスト プラクティスについては、このドキュメントの「ベスト プラクティス」で説明します。

ベスト プラクティス

このドキュメントの残りの部分では、Windows Azure と SQL データベースを使用して拡張性の高いアプリケーションを提供するためのベスト プラクティスを紹介します。これらは、実際の経験と、そこから得られた教訓に基づいています。各ベスト プラクティスについて、対象となる最適化とコンポーネント、実装方法、および固有のトレードオフを説明します。これらの推奨事項は、すべてのベスト プラクティスと同様に、適用されるコンテキストに大きく依存します。前のセクションで説明したプラットフォームの機能に基づいて各ベスト プラクティスの適合性を評価してください。

note
これらの経験は、従来の OLTP (オンライン トランザクション処理) のパターンに従っていないいくつかの顧客契約から得られたものです。これらのベスト プラクティスの中には、厳密なデータの一貫性が必要なアプリケーションにはそのまま適用できないものもあります。個々のアプリケーションおよびその環境のビジネス要件に基づいて判断してください。

各ベスト プラクティスは、以下の 1 つ以上の最適化の側面に関連しています。

  • スループット。システムで処理される操作 (トランザクション、サービスの呼び出しなど) を増やして競合を減らす方法。

  • 待機時間。個々の操作と全体の合計の両方の待機時間を減らす方法。

  • 密度。直接 (SQL データベースを操作するアプリケーション コードなど) および集計 (規模の増大のために複数のストレージ アカウントを活用する場合など) の両方のコンテキストでサービスを構成する場合に競合ポイントを減らす方法。

  • 管理の容易性。診断、遠隔測定、検証など、配置されたサービスの状態とパフォーマンスを大規模に把握する方法。

  • 可用性。障害点と障害モードの影響を軽減してアプリケーション全体の可用性を高める方法 (負荷の下での可用性は、スループット、待機時間、密度でカバーされます)。

クラウド サービス

拡張性と可用性に優れたサービスを提供するためには、Windows Azure の基本スケール単位となるホステッド サービスを慎重に設計および配置することが重要です。

  • ホステッド サービス内のインスタンスとアップグレード ドメインの数は、ホステッド サービスの配置、構成、およびアップグレードに要する時間に大きく影響します。パフォーマンスおよびスケーラビリティのメリットと複雑さの増加との兼ね合いを考慮する必要があります。一般に、スケーラビリティと柔軟性の向上にはソリューションの開発コストと管理コストの増加が伴います。

  • 単一インスタンスのロールを避けます。この構成は、Windows Azure SLA の要件を満たしていません。単一インスタンスのロールは、ノードの障害やアップグレードの際にオフラインになります。優先度の低い "メンテナンス" タスク以外には使用しないでください。

  • すべてのデータ センターは容量が (大きいとは言え) 限られており、ごくまれに単一障害点になることがあります。最高レベルの拡張性と可用性を必要とするサービスでは、複数のホステッド サービスを含むマルチデータ センター トポロジを実装する必要があります。ただし、

  • 最高レベルの可用性が必要とされない場合は (上の項目を参照)、アプリケーションと依存サービスが 1 つのデータ センターに完全に含まれていることを確認します。ソリューションで複数のデータ センターを使用する必要がある場合は、次のガイドラインに従ってください。

    • ライブ操作ではデータ センター間のネットワーク呼び出しを避けます (意図的なサイト間の同期を除く)。データ センター間の待機時間は長時間にわたり、変動が大きいため、アプリケーションのパフォーマンスに予期しない (望ましくない) 影響を与える可能性があります。

    • 別のデータ センターのサービスにアクセスする機能は必要最小限に抑えます。通常、これらの操作は、ビジネス継続性とデータのレプリケーションに関連しています。

分散 Caching

大規模な分散アプリケーションでは、ステートフルなアプリケーション データへのアクセスが重要になります。一般に、アプリケーション全体のスループットと待機時間は、必要なデータとコンテキストをいかに早く取得、共有、および更新できるかにかかっています。Windows Azure Caching や memcached などの分散キャッシュ サービスは、こうしたニーズに応えて進化してきました。アプリケーションで分散キャッシュ プラットフォームを活用する必要があります。次のガイドラインを考慮してください。

  • 分散キャッシュ プラットフォームをホステッド サービス内のワーカー ロールとして使用します。このようにキャッシュをクライアントに近づけることにより、ロード バランサーの通過による待機時間とスループットの障壁を削減できます。Windows Azure キャッシュのインロール キャッシュは、クラウド サービス内のワーカー ロールのキャッシングをホストします。

  • 共通のアプリケーション データやオブジェクト (ユーザー プロファイルやセッション状態など) にアクセスするためのプライマリ リポジトリとして分散キャッシュ プラットフォームを使用し、SQL データベースやその他の永続的なストアでリード スルーまたはキャッシュ アサイドのアプローチでサポートします。

  • キャッシュ オブジェクトには、分散キャッシュでアクティブになる期間に影響する有効期限があります。アプリケーションでは、キャッシュされるオブジェクトの有効期限を明示的に設定するか、キャッシュ コンテナーの既定の有効期限を構成します。有効期限を選択するときは、可用性 (キャッシュ ヒット) とメモリの負荷やデータの鮮度とのバランスを考慮するようにしてください。

  • キャッシュでは、キー -> byte[] セマンティクスが使用されます。重複する書き込みによってキャッシュのデータに不整合が生じる場合があることに注意してください。分散キャッシュでは、格納されたデータの構造を認識しないため、格納されたデータに対してアトミックな更新を行うための API は提供されません。

    • 同時実行の書き込みの一貫性を厳密に確保する必要があるアプリケーションでは、エンティティを更新する際のロック メカニズムを備えた分散キャッシュ プラットフォームを使用します。Azure Caching の場合は、GetAndLock/PutAndUnlock で実装できます。ただし、スループットが低下することに注意してください。

  • キャッシュのパフォーマンスは、アプリケーション層でのオブジェクトのシリアル化とシリアル化解除にかかる時間に制限されます。この処理を最適化するには、対称性が比較的高い (データのエンコードとデコードにかかる時間が同じ)、効率的なバイナリ シリアライザー (protobuf など) を利用します。

    • カスタムのシリアル化を正しく使用するには、キャッシュにシリアル化するデータ転送オブジェクト (DTO) を設計し、シリアル化に対する適切な注釈を使用して、循環依存を回避し、単体テストを活用して効率的なシリアル化を追跡します。

接続のアフィニティ

既定では、サービスの階層間の接続 (ロード バランサーを介した着信接続を含む) には、接続の固定が制限されたラウンドロビン割り当て方式が適用されます。次の図は、階層と外部サービスの間の一般的な接続のメッシュを示しています (左側は Web 層のみの一般的なアプリケーションです)。このメッシュには簡易接続プロトコル (HTTP など) のパフォーマンスに関する大きな問題はありませんが、特定の接続については、接続や初期化の負担が大きいか、リソースが抑制 (制限) されているかのどちらかです。たとえば、SQL データベース接続はこれに該当します。これらの外部サービスとコンポーネントの使用を最適化するには、アフィニティを実装してリソース呼び出しを特定のインスタンスに関連付けることを強くお勧めします。

接続関係

この図の右側のトポロジでは、同じホステッド サービス内に独立した Web 層とワーカー層 (ロール) があります。また、Web 層とアプリケーション層の間のアフィニティが実装され、特定のアプリケーション インスタンスから特定のデータベースへの呼び出しが固定されています。たとえば、Web インスタンスでデータベース 1 (DB1) のデータを要求するには、アプリケーション インスタンス 1 または 2 を介して要求する必要があります。現在、Windows Azure のロード バランサーにはラウンドロビン方式しか実装されていないため、アプリケーションでアフィニティを提供する場合は慎重に設計して実装する必要があります。

  • Web 層とアプリケーション層を分けてアプリケーションを設計し、Web 層とアプリケーション層の間にパーティションまたはリソース対応アフィニティを実装します。

  • サービス内の呼び出しを対象のアプリケーション インスタンスに透過的にルーティングするルーティング ロジックを実装します。外部または下流のリソース (SQL データベースなど) で使用されているパーティション分割メカニズムのナレッジを使用します。

複数の層で構成されるこのアーキテクチャを実際に実装するときは、効率的な簡易プロトコルを使用して、Web 層とアプリケーション層の間のサービスの通信を効率化する必要があります。

コンピューティングとアプリケーション コード

Windows Azure アプリケーションの開発方法は、基本的には Windows Server の場合と同じです。ただし、柔軟なファブリックを構築するためには、必要性と利点の両面から、コンピューティング リソースを最も効果的に使用する効率的なコードを使用することが特に重要になります。

  • いずれのサービス、ネットワーク呼び出し、依存リソースについても信頼できるものとは見なさず、一時的および継続的な障害モードの対象に含めるようにします (例として、SQL データベースに対する再試行ロジックの実装方法をこのトピックで後ほど説明します)。

    • 一時的なエラー状態や接続の切断に対処するために、すべてのサービス呼び出し (SQL データベース、ストレージなど) に対して適切な再試行ポリシーを実装します。

    • "コンボイ" の影響 (サービスで再試行が繰り返されて停止が長引く状況) を回避するために、再試行ロジックにバックオフ ポリシーを実装します。

    • エラー メッセージや障害イベントをコンテキスト情報 (対象のサービス、ユーザーやアカウントのコンテキスト、利用状況など) と共に記録するための機能豊富なクライアント側遠隔測定を実装します。

  • 作業のスケジュール設定を行う際は、スレッドを直接作成するのではなく、.NET のタスク並列ライブラリなどのスケジュール設定および同時実行制御フレームワークを利用します。スレッドは比較的大きなオブジェクトであり、作成や破棄が簡単ではありません。共有スレッド プールに対して機能するスケジューラを使用すると、作業のスケジュール設定や実行をより効率的に行うことができます。また、このアーキテクチャにより、継続性やエラー処理も向上します。

  • シリアル化およびネットワーク転送のデータ転送オブジェクト (DTO) を最適化します。Windows Azure アプリケーションは高度に分散されることから、スケーラビリティを高められるかどうかは、システムの個々のコンポーネントがネットワーク経由でいかに効率よく通信できるかにかかっています。通信や保存のためにネットワーク経由で渡されるデータには、JSON テキストのシリアル化や効率が高いバイナリ形式を実装して、ネットワーク経由で転送されるメタデータの量が最小限で済むように適切なヒントを設定します (送信時にフィールド名を短くするなど)。

    • 相互運用が重要な場合は、相互運用性および帯域内のメタデータに、効率が高いテキスト形式 (JSON など) を使用します。

    • サービス間の通信の両端を制御する場合など、高いスループットが重要な場合は、効率が高い圧縮されたバイナリ形式 (bson や protobuf など) を検討します。

      • 小さなデータ オブジェクトの chatty (頻繁) なデータ転送を回避します。chatty なサービス間通信により、オーバーヘッド タスクで大量のシステム リソースが浪費され、応答の待機時間の変化による影響を受けやすくなります。

      • 自動テスト フレームワークの主要なコンポーネントとして、オブジェクトのシリアル化とシリアル化解除のテストを行います。機能テストを実施して、データ クラスがシリアル化可能であること、および循環依存がないことを確認します。また、パフォーマンス テストで、必要な待機時間とエンコードのサイズを確認します。

  • 必要に応じて、コンポーネントとサービスの間の通信に簡易フレームワークを活用します。.NET の従来のさまざまなテクノロジで提供される豊富な機能は、分散型の性質を持つ Windows Azure には適さないことがあります。目的から実行までの間が高度に抽象化されたコンポーネントでは、多くの場合、パフォーマンス コストが増大します。

    • プロトコルの相互運用や高度なプロトコルのサポートを必要としない場合は、Web サービスの実装に WCF ではなく ASP.NET Web API を使用することを検討します。

    • Entity Framework の豊富な機能を必要としない場合は、SQL クライアント レイヤーの実装に Dapper などの Micro-ORM を使用することを検討します。

  • 送信データに対して IIS の HTTP 圧縮を有効にして、データ センターから配信されるデータの量を減らします。

  • 階層間の接続のアフィニティを実装して、chatty な通信や接続のコンテキスト切り替えを減らします。

  • アプリケーションの負荷を軽減するために、サイズが大きい (> 100 KB) 静的なコンテンツを提供するときは、BLOB ストレージを使用します。

  • アプリケーションの負荷を軽減するために、画像や CSS などの静的なコンテンツを提供するときは、BLOB ストレージを利用したコンテンツ配信ネットワーク (CDN) を使用します。

  • セッション データには SQL データベースを使用しないようにします。代わりに、分散キャッシュまたは Cookie を使用します。

ストレージ

Windows Azure ストレージは、Windows Azure アプリケーションの永続的なデータのバックボーンです。追加設定なしで高い信頼性と拡張性を実現できますが、大規模なアプリケーションでは、設計と使用方法に関する適切なガイドラインが必要になります。

  • サイズの増大 (> 100 TB) やスループットの増加 (> 5,000 操作/秒) に対応できるようにスケーラビリティを向上させるには、複数のストレージ アカウントを使用します。複数のストレージ アカウントを使用するようにアプリケーション コードを構成できることを確認し、適切なパーティション関数を使用してストレージ アカウントに作業をルーティングします。ストレージ アカウントを追加する機能の設計は、コードの変更ではなく、構成の変更で行います。

  • テーブル ストレージのパーティション関数を選択するときは、挿入とクエリのパフォーマンスを考慮して目的の規模に対応するものを選択します。遠隔測定データには時間ベースのパーティション分割アプローチを使用し、一時的なデータ以外の行データに基づく複合キーを使用します。最適なパフォーマンスを得るには、パーティションの範囲を適切に維持する必要があります。パーティションが小さすぎるとバッチ操作 (クエリを含む) の実行が制限され、パーティションが大きすぎるとクエリの負荷が増大します (大量の挿入を同時に行うときにボトルネックになることもあります)。

    • パーティション関数の選択は、基本的なクエリのパフォーマンスにも影響します。テーブル ストレージでは、{パーティション キー, 行キー} で効率的な参照が可能ですが、{パーティション キー, 行一致フィルター} や {パーティション キー一致フィルター, 行キー一致フィルター} の場合は処理効率が低下します。クエリでは、グローバルなテーブル スキャン ({行キー一致フィルター}) が必要です。

    • パーティションは、エンティティが 1 つだけでも構成できます。これにより、ショッピング カートの管理のような純粋な参照ワークロードのパフォーマンスが大幅に最適化されます。

  • 可能であれば、ストレージに対する操作にはバッチ処理を使用します。テーブルへの書き込みは、通常は .NET クライアント API の SaveChanges メソッドでバッチ処理します。一連の行をテーブルに挿入してから、SaveChanges メソッドを使用して 1 つのバッチで変更をコミットします。BLOB ストレージに対する更新も、PutBlockList メソッドを使用してバッチでコミットします。テーブル ストレージの API と同様に、PutBlockList は、個々のブロックではなく一連のブロックに対して呼び出します。

  • テーブルのプロパティでは短い列名を使用します。メタデータ (プロパティ名) は帯域内に格納されるため、列名も行の最大サイズ (1 MB) のカウントに含められるからです。プロパティ名が長すぎるとシステム リソースの浪費になります。

SQL データベース

「Windows Azure クラウド サービスの検証」で説明したように、SQL データベースを使用すると、ターンキー リレーショナル データベースをサービスとして提供し、スケールアウトによってデータ ストレージへのアクセスを拡張することができます。大規模なアプリケーションで SQL データベースを正しく使用するために、設計と実装に関して注意が必要な事項がいくつかあります。ここでは、設計に関する主なポイントとベスト プラクティスを示します。

多くのアプリケーションには、ルーティング、パーティション分割、テナント情報などの詳細を格納するメタデータ テーブルが必要です。このメタデータを 1 つのデータベースに格納すると、単一障害点になるだけでなく、スケーラビリティのボトルネックにもなります。中央のメタデータ ストアは、次の方法を組み合わせてスケールアウトする必要があります。

  • キャッシュの活用。構成データベース内の情報は、分散キャッシュ (Memcached や Windows Azure Caching など) にできるだけキャッシュするようにします。

    • アプリケーションの起動時に複数のワーカー スレッドから事前にキャッシュを読み込もうとすると、通常、負荷やデータベースの調整が増えることに注意してください。アプリケーションでキャッシュを事前に読み込む必要がある場合は、読み込み速度の構成が可能な専用のワーカー ロール (または定期タスク) でデータを読み込む必要があります。

    • アプリケーションのパフォーマンスや信頼性が特定のデータ セグメントをキャッシュで使用できるかどうかで決まる場合は、キャッシュの事前読み込みが完了するまで受信要求を拒否するようにします。データが読み込まれるまでは、該当するエラー メッセージまたはコードを返す必要があります。

  • スケールアウト。データを縦方向 (テーブルごと) または横方向 (複数のシャードにテーブルを分割) にパーティション分割して、複数のデータベースに負荷を分散します。

パーティション分割した SQL データベースの全体的なスケーラビリティは、個々のデータベース (シャード) の規模に加え、規模の増大に応じてそれらのシャードをいかに効率的かつ効果的にまとめられるかで決まります。

  • インデックスの再構築のようなより大きなトランザクションにはトランザクション ログの制限が適用されるため、個々のテーブルの上限は約 10 GB になります (実際の制限は対象のテーブルのインデックスのサイズで決まるため、データベースによっては 10 GB より大きくなる場合や小さくなる場合があります)。個々のテーブルのサイズが大きい場合は、複数の小さいテーブルに分割し、パーティション ビューを使用してオーバーレイを一定にします。

    • 個々のテーブルのサイズを小さくすると、段階的なアップグレードにおけるスキーマの変更やインデックスの再構築による影響が少なくなります。複数の小さいテーブルに対して変更を行うことで、操作がブロックされることによるダウンタイムや待機時間を最小限に抑えることができます。

    • このようなパーティション分割を行うと、管理方法が複雑になります。インデックスの再構築などの操作は、すべてのコンポーネント テーブルに対して反復方式で実行する必要があります。

  • 個々のデータベース (シャード) は妥当なサイズまで小さくします。データベースのサイズが 50 GB を超える場合、データベース コピーやエクスポートなどの継続性操作が完了するまでに何時間もかかることがあります (サービスの取り消し操作には 24 時間以上かかります)。

継続的にサービスを提供するために、分散したデータベースの更新やスキーマの変更を管理する際は、スムーズにアップグレードできるように十分な注意が必要です。実稼働データ ストアでのスキーマやメタデータの操作の制御に関する従来のベスト プラクティスはいずれも、以前にも増して重要になっています。たとえば、データベースが 100 個あれば、そのうちの 1 つで誤ってストアド プロシージャを削除した場合にデバッグして解決する作業がはるかに複雑になります。

スキーマの更新やデータの変更により、シャード間でトランザクションの一貫性が保持されない状態になるため、アプリケーションの更新では、移行期間中に古いスキーマと新しいスキーマの両方との互換性を確保する必要があります。通常、アプリケーションの各リリースでは、少なくともスキーマの現在のバージョンと前のバージョンとの互換性が必要になります。

接続の管理

データベースのコレクションをスケールアウトに切り替えるときは、接続の管理に関する課題が伴います。SQL データベース接続は、それぞれクライアント API (ADO.NET、ODBC、PHP など) の接続プールを多用することからわかるように、比較的コストが高いリソースです。それぞれのアプリケーション インスタンスで、中央の SQL Server への接続を複数保持するのではなく、複数のデータベース サーバーへの接続を保持する必要がある場合もあります。

コストがかかり、数にも限りがあるリソースとなれば、プールされた接続を適切なタイミングで返すことで接続を適切に管理することが必要になります。そのため、アプリケーション コードで接続の自動破棄を使用します。.NET の場合のベスト プラクティスは、次のように、使用するすべての SqlConnectionusing ステートメント内にラップすることです。

using (var conn = new SqlConnection(connStr))
{
    // SQL client calls here
}

既に説明したように、SQL データベースに対する接続は一時的な接続エラーの影響を受けます。それらの一時的なエラーから保護するには、すべての接続およびコマンドで再試行ロジックを使用する必要があります (詳細についてはこの後に説明します)。

SQL データベースでは TCP 接続しかサポートされない (名前付きパイプはサポートされません) ため、アプリケーション コードと SQL データベースの間の接続は暗号化することを強くお勧めします。意図しない接続の試行 (名前付きパイプの使用など) を防ぐには、次のような形式の SQL 接続文字列を使用します。

Server=tcp:{servername}.database.windows.net,1433;Database={database};User ID={userid}@{database};Password={password};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;

大規模なアプリケーションの配置では、ホステッド サービスの配置と SQL データベース クラスター内の SQL データベースの論理サーバーの間で、潜在的な接続の既定の数が指数関数的に増える可能性があります (それぞれに 1 つずつ外部 IP アドレスが割り当てられます)。たとえば、インスタンスが 100 個でデータベースが 50 個のホステッド サービスについて考えてみましょう。接続の数は、ADO.NET の既定の 100 個です。

MaxConnections=DatabaseCount*Instance Count*MaxConnectionPoolSize

ホステッド サービスのネットワーク トポロジに関しては、接続のそれぞれの側 (ホステッド サービスと SQL データベースの論理サーバー) が Windows Azure のロード バランサーの背後にあります。.Windows Azure の各ロード バランサーにおける任意の 2 つの IPv4 アドレスの間の接続数の上限は 64,000 です。したがって、このネットワーク トポロジと使用可能な既定の接続数の組み合わせでは、大規模なアプリケーションで重大なネットワーク障害が発生します

  • 大規模なアプリケーションの場合は複数のホステッド サービスに配置します。

  • データベースを (同じサブスクリプションの複数の論理サーバーだけでなく) 複数のサブスクリプションで配置して、一意の IP アドレスの数を増やします。

  • 複数の層から構成されるアプリケーションを実装して、送信操作を対象のアプリケーション インスタンスに関係付けます (ホステッド サービスに関する前のセクションを参照してください)。

  • 接続プールは一意の接続文字列ごとに保持され、データベース サーバー、データベース、およびログインの一意の組み合わせに対応することに注意してください。SQL クライアントの接続プールを使用し、SQL 接続プールの最大サイズを明示的に制限します。SQL クライアント ライブラリでは、必要に応じて接続を再利用します。接続プールが小さいと、接続を使用できるようになるまでのアプリケーションの待機時間が長くなる可能性があります。

必要になるアクティブな接続の数を少なくするための推奨事項を以下に示します。

スキーマとクエリのデザイン

分散データ モデルに移行する際、データベース スキーマのデザインや特定の種類のクエリについて、変更が必要になることがあります。複数のデータベース間で分散トランザクションを使用する必要があるアプリケーションに、不適切なデータ モデルや実装が含まれる可能性があります (たとえば、全体的な一貫性を強制する場合などが該当します)。それらのデザインはリファクターする必要があります。

可用性やスケーラビリティの制約から、アプリケーションの重要な部分には中央のシーケンス生成機能を使用しないようにしてください。多くのアプリケーションでは、シーケンスを利用してグローバル一意識別子を提供し、中央の追跡メカニズムを使用して要求時にシーケンスを増分しています。このアーキテクチャにより、システムの各コンポーネントでの操作を必要とする全体的な競合ポイントやボトルネックが発生します。このボトルネックは、切断される可能性があるモバイル アプリケーションで特に問題になります。

代わりに、分散システムでグローバル一意識別子 (GUID) を生成できる関数を利用します。仕様上、GUID はシーケンシャルではないため、大きなテーブルでクラスター化インデックスとして使用すると断片化の原因となることがあります。大きなデータ モデルにおける GUID による断片化の影響を軽減するには、データベースをシャード化し、個々のシャードを小さくします。これにより、レプリカのフェールオーバー時に、SQL データベースによって自動的にデータベースがデフラグされるようになります。

クライアントのアプリケーション コードでは、分散データ モデルの配信に関して以下を考慮する必要があります。

  • パーティション キー。パーティション キーはすべてのデータ クラスまたはモデルに含め、パーティション キーの検出を許可する属性で修飾する必要があります。

  • 遠隔測定。すべての SQL 呼び出しに関する情報をデータ アクセス レイヤーで自動的に記録する必要があります。この情報には、対象、パーティション、コンテキスト、待機時間のほか、エラー コードや再試行がある場合はそれらも含まれます。

  • 分散クエリ。複数のシャードにまたがるクエリを実行する場合は、ルーティング、パーティションの選択、部分成功 (個々のシャードによって正常にデータが返されるものと返されないものがある) の概念など、いくつかの新しい課題が伴います。データ アクセス レイヤーで、非同期 (並列) のスキャッター/ギャザーの方式で分散クエリを実行するデリゲートを用意し、複合的な結果を返す必要があります。分散クエリでは、基になるリソースの制限についても考慮する必要があります。

    • 並列処理の最大限度 (スレッドや接続の過剰な負荷を回避するため)。

    • 最大クエリ時間 (時間がかかるクエリや低速なシャードによる全体的な待機時間を減らすため)。

さらに、いくつかの管理タスクを継続的に行う必要があります。

  • 参照テーブル。全体に一貫性があるクエリ領域がない場合は、クエリの結合の参照データを個々のシャードにコピーする必要があります。個々のシャードの参照テーブルにデータをレプリケートして保持することで、ローカルの参照データをある程度一貫した状態にしておく必要があります。

  • パーティションの再調整。個々のパーティションが不均衡な状態になり、使用されるリソースが多すぎて停滞したり、リソースが十分に使用されずに無駄になったりする場合があります。このような場合は、パーティションを再度均衡化させてリソースの再割り当てを行う必要があります。再度均衡化させるメカニズムは、パーティション分割方法とその実装に大きく依存します。ほとんどのシナリオでは、再均衡化は一般に次の処理を伴います。

    • 分割/マージ メカニズム (範囲に基づくパーティション分割の場合) またはエンティティ レベルのコピーと再マップ (参照に基づくパーティション分割の場合) を使用して、シャードの既存のデータを 1 つ以上の新しいシャードにコピーします。

    • シャードのマップが新しいシャードを指すように更新し、移行中に古いシャードに書き込まれたデータの補正を行います。

  • データのクリーンアップ。アプリケーションでの収集データの増加に合わせ、使用しない古いデータを定期的にクリーンアップして、プライマリ システムの使用可能なヘッドルームと容量を増やすことを検討します。クリーンアップ (削除) するデータは、SQL データベースから同期的に削除されるのではなく、削除対象のフラグが設定され、バックグラウンド プロセスでクリーンアップされます。データに削除対象のフラグを設定する一般的な方法は、フラグ列で行がアクティブ、非アクティブ、または削除対象のいずれであるかを示す方法です。これにより、データを一定の期間にわたってクエリからマスクし、データがまだ必要な場合は簡単に運用に戻すことができます。

    データを削除すると断片化が生じる可能性があり、効率的なクエリ処理のためにインデックスの再構築が必要になることがあります。古いデータは以下にアーカイブできます。

    • オンライン ストア (セカンダリ SQL データベース)。プライマリ システムのヘッドルームは増えますが、コストの削減にはなりません。

    • オフライン ストア (BLOB ストレージの bcp ファイルや bacpac ファイルなど)。プライマリ システムのヘッドルームが増え、コストの削減にもなります。

    • ビット バケット。プライマリ システムからデータを完全に削除してヘッドルームを増やすことができます。

一時的なエラーの処理とバックオフ

SQL データベースでは、レプリカのフェールオーバーなど、いくつかの一般的な状況で、一時的な接続エラーが発生することがあります。アプリケーションで適切なコードを実装して、一時的なエラーを処理し、リソースの枯渇や調整に正しく対処する必要があります。

  • 再試行による一時的な接続エラーの処理。データ アクセス コードで、一時的な接続エラーを補正するためのポリシーに基づく再試行メカニズムを利用します。この再試行メカニズムでは、一時的な接続エラーを検出し、対象の SQL データベースに再接続して、コマンドを再実行します。

  • 再試行およびバックオフ ロジックによる調整の処理。データ アクセス コードで、調整状態に対処するためのポリシーに基づく再試行およびバックオフ メカニズムを利用します。この再試行メカニズムでは、調整を検出し、少しずつバックオフしながらコマンドを再実行します (調整状態を長引かせる可能性があるコンボイの影響を回避するため)。

    • データ アクセス コードでは、BLOB ストレージなどの代替データ ストアにバックオフする機能も実装することをお勧めします。この代替ストアを利用状況、データ、および状態をキャプチャするための持続的なメカニズムとして使用することで、調整や可用性のイベントが長時間続く場合のデータの損失を回避することができます。

.NET アプリケーションでは、Cloud Application Framework (CloudFx)Enterprise Library Transient Fault Handler など、SQL データベースに対応した再試行およびバックオフ ロジック フレームワークを使用できます。これらのフレームワークには、一般的なデータ アクセス クラス (SqlConnection や SqlCommand など) のラッパーと、直接呼び出すことができるポリシーが用意されています。

var retryPolicy = RetryPolicy.Create<SqlAzureTransientErrorDetectionStrategy>(
    retryCount: 3, 
    initialInterval: TimeSpan.FromSeconds(5),
    increment: TimeSpan.FromSeconds(2));
                
using (var conn = new ReliableSqlConnection(connStr))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {

    }
    conn.Close();
}

このコード例では、CloudFx の ReliableSqlConnection クラスを使用して、SQL データベースの操作時の一時的な接続エラーを処理する方法を示しています。

アプリケーション/クライアントの遠隔測定

SQL データベースなどのサービスの API 呼び出しに関するログを記録する際は、障害モードが複雑になることがあるため一定の注意が必要です。コンテキストやパフォーマンスの情報の重要な部分をキャプチャするようにします。たとえば、SQL データベース セッションには、いずれにもセッション識別子があります。この識別子をサポート呼び出しで使用することで、原因となっている問題を直接特定することができます。SQL データベースのログには、すべての呼び出し、コマンド、およびクエリを記録することを強くお勧めします。

  • サーバーおよびデータベース名。データベースの数は何百にもなることがあるため、問題を追跡して特定するには、対象のサーバーを特定することが重要です。

  • SQL のストアド プロシージャやコマンド テキスト (適切な場合)。機密情報がログ ファイルに漏れないように注意が必要です。一般に、コマンド テキストはログに記録しないようにします。

  • 呼び出しの端末間の待機時間。ストップウォッチなどの簡易タイマーを使用して、タイミングのデリゲートで呼び出しをラップします。

  • 呼び出しの結果コード (成功または失敗)、再試行の回数、および失敗の原因 (接続の切断、調整など)。

  • 接続のセッション ID。この情報は、CONTEXT_INFO() プロパティ (ReliableSqlConnection を使用する場合は SessionTracingId プロパティ) で確認できます。ただし、CONTEXT_INFO() コマンドでセッション ID を取得する際にサーバーへのラウンド トリップが発生するため、このコマンドはすべてのクライアント呼び出しでは実行しないようにします。

バッチ処理と非同期実行

SQL データベースをより効率よく使用できるように、可能であれば、SQL データベースに対するクエリやデータ挿入はバッチ処理で非同期に実行します。これにより、アプリケーションの効率が向上するだけでなく、SQL データベースのシステム全体の負荷も軽減されます (スループットが向上します)。

  • 挿入のバッチ処理。新しいユーザーの登録など、連続的なデータ挿入操作では、データをバッチ処理して対象のシャードに配置します。これらのバッチは、対象のバッチ サイズや時間枠などのトリガーに基づいて、SQL データベースに定期的 (非同期) に書き込む必要があります。バッチ サイズが 100 行未満であれば、通常、テーブル値関数の方が一括コピーよりも効率的です。

  • chatty なインターフェイスの回避。クエリや一連の操作を実行するために必要なデータベースへのラウンド トリップの回数を少なくします。chatty なインターフェイスはオーバーヘッドが大きいため、システムの負荷が増え、スループットや効率が低下します。関連する操作をマージし、ストアド プロシージャなどを使用してラウンド トリップを減らすようにしてください。

ビジネス継続性とデータ管理

ビジネス継続性のための全体的な方法の一環として、SQL データベースに格納されているデータを定期的に BLOB ストレージにエクスポートする必要があります。BLOB ストレージでは、可用性と地理分散が既定でサポートされます。

データベースを定期的に BLOB ストレージにエクスポートする定期タスクを実装します。これには、専用のストレージ アカウントを使用します。このタスクは、オンプレミスのデスクトップやサーバーではなく、対象のデータベースと同じデータ センターで実行する必要があります。

エクスポート タスクは、エンド ユーザー エクスペリエンスへの影響を最小限に抑えるために、使用率が低いときに実行するようにスケジュールします。複数のデータベースをエクスポートする場合は、システムへの影響を少なくするために並列エクスポートの最大数を制限します。

SQL データベースの遠隔測定

総合的なサービスの提供においては、SQL データベースの状態、パフォーマンス、およびヘッドルームを把握することが重要になります。SQL データベースでは必要な未加工の情報を動的管理ビューで確認できますが、現在のところ、主要な基準を取得、分析、およびレポートするためのターンキー インフラストラクチャはありません。SQL データベース向けにこの機能を提供するには、次の方法を検討してください。

  • システムの負荷、使用されるリソース (ワーカー スレッド、ストレージ領域)、およびデータに関する主要なパフォーマンス データを収集して共通のリポジトリに格納する定期タスクを実装します。たとえば、Windows Azure 診断で使用されるテーブルを検討してください。このタスクでは、アプリケーションに属するすべてのデータベースのデータを収集する必要があります。これは、通常はスケールアウトで実行します (複数のデータベースのデータを同時に収集します)。

  • 配置されているデータベースの状態や容量の主要業績評価指標を作成するためにこの情報を集計する定期タスクを実装します。

遠隔測定と診断

アプリケーションおよびインスタンス レベルの遠隔測定を収集するベースラインは、Windows Azure 診断で提供されます。ただし、Windows Azure で実行される大規模なアプリケーションの情報を提供するには、データ フローを慎重に構成して管理する必要があります。Windows の豊富な診断ユーティリティを利用できる集中管理型のスケールアップ アプリケーションとは異なり、分散型のスケールアウト システムでは、運用の開始前に診断を実装する必要があり、後で行うというわけにはいきません

エラー イベント、根本原因、および解決方法を特定するためには、エラー処理、コンテキストのトレース、および遠隔測定のキャプチャが重要になります。

  • 運用環境のサイトのデータと遠隔測定を同じストレージ アカウントにパブリッシュしないでください。診断には専用のストレージ アカウントを使用します。

  • chunky な遠隔測定 (大量、待機時間が長い、詳細なデータ) と chatty な遠隔測定 (少量、待機時間が短い、重要度が高いデータ) のそれぞれに対応する別々のチャネルを作成します。

    • chatty な情報には、パフォーマンス カウンターやトレースなど、Windows Azure 診断の標準のソースを使用します。

    • ローカル ファイルへの一括ログ記録を実装するには、Enterprise Application Framework Library、log4net、NLog など、一般的なログ記録ライブラリを使用します。診断モニターの構成でカスタム データ ソースを使用して、この情報を BLOB ストレージに定期的にコピーします。

  • 外部サービスのすべての API 呼び出しについて、コンテキスト、対象、方法、タイミング情報 (待機時間)、および結果 (成功/失敗/再試行) を記録します。膨大な遠隔測定の情報で診断システムの負荷が大きくならないように、chunky なログ チャネルを使用します。

  • テーブル ストレージに書き込まれるデータ (パフォーマンス カウンター、イベント ログ、トレース イベント) は、60 秒ごとに一時的なパーティションに書き込まれます。書き込むデータの量が多すぎる (参照するソースが多すぎる、収集間隔が短すぎる) と、このパーティションに対する負荷が大きくなることがあります。調整イベントが発生する可能性があるため、エラーの急増によってテーブル ストレージへの大量の挿入が行われないようにしてください。

    • 重要なパフォーマンス カウンター、重大なイベントとエラー イベント、トレース レコードなど、ソースから重要度が高いデータを選択して収集します。

    • 適切な収集間隔 (5 ~ 15 分) を選択して、転送および分析が必要なデータの量を少なくします。

  • インスタンスを強制的にリセットせずに、実行時にログ構成を変更できるようにします。また、データベース、キャッシュ、その他のサービスなど、システムの特定の側面について、個別にログを有効にできることを確認します。

Windows Azure 診断では、SQL データベースや分散キャッシュなど、依存サービスのデータは収集されません。アプリケーションやそのパフォーマンス特性を総合的に示すには、依存サービスのデータを収集するためのインフラストラクチャを追加します。

  • 依存サービスからパフォーマンスと利用状況に関する主要なデータを収集し、パフォーマンス カウンターのレコードとして WAD リポジトリにパブリッシュします。

    • Windows Azure ストレージ分析の Windows Azure ストレージのデータ

    • 動的管理ビューの SQL データベースのデータ

    • パフォーマンス カウンターまたは状態監視 API の分散キャッシュのデータ

  • 定期的に未加工の遠隔測定データを分析して集計やロールアップを行います (定期タスクを使用します)。

コミュニティの追加

追加
表示:
© 2014 Microsoft