次の方法で共有



April 2011

Volume 26 Number 04

クラウド キャッシュ - Windows Azure AppFabric キャッシュ サービスの概要

Karandeep Anand | April 2011

ソリューション成功の基準として速度と規模が重要視される環境 (アプリケーションの設計段階でも、速度と規模を設計の主要原則とする必要がある環境) では、アプリケーション アーキテクチャに後から付け加えたり、手を加えたりすることはできません。

Windows Azure AppFabric キャッシュ サービスは、アプリケーション アーキテクチャに追加の層を展開して管理することを学ぶ必要なく、こうした問題を簡略化するために必要なビルディング ブロックを提供します。一言で言うと、キャッシュ サービスとは柔軟性の高いメモリのことで、アプリケーションのコンピューター処理層を容易にスケール アウトできるようデータ層や分散状態の負荷を取り除くことによって、パフォーマンスやスループットを向上するために必要なものです。

キャッシュ サービスは、2010 年の Microsoft Professional Developers Conference で Community Technology Preview (CTP) 版としてリリースされ、2011 年 2 月に最新バージョンに更新されました。

キャッシュ サービスは、Windows Azure プラットフォームの重要な構成要素の 1 つで、現在の Windows Azure プラットフォームを構成する Platform as a Service (PaaS) の提供サービスを基盤に構築されています。また、Windows Server AppFabric キャッシュと同じコード ベースに基づいているため、オンプレミス (社内設置型) のキャッシュの開発エクスペリエンスと対称性があります。

キャッシュ サービスは、開発者に次の機能を提供します。

  • あらかじめ構築済みの、セッション状態とページ出力キャッシュ用の ASP.NET プロバイダー (アプリケーション コードを変更する必要なく Web アプリケーションを高速化できる)
  • あらゆるマネージ オブジェクトをキャッシュ (オブジェクト サイズに制限がなく、ローカル キャッシュにシリアル化のコストがかからない)
  • 既存のアプリケーションへの容易な統合
  • Windows Azure AppFabric と Windows Server AppFabric 間で一貫した開発モデル
  • Access Control Service によって提供されるセキュアなアクセスと承認

クラウド内のインスタンスとして、独自に他のキャッシュ テクノロジ (memcached など) をセットアップすることもできますが、その場合、開発者自身がキャッシュ クラスターとインスタンスをインストール、構成、および管理しなくてはなりません。そのため、こうした細かい管理を行わなくて済むようにすることが、クラウドや (特に) PaaS の主な目標の 1 つになっています。Windows Server AppFabric キャッシュ サービスは、このような負担を開発者から取り除くと同時に、コードや構成を少し変更するだけで (またはまったく変更しないで) Windows Azure で実行される ASP.NET Web アプリケーションのパフォーマンスを向上します。ここでは、これがどのように実現されているかを解説します。

キャッシュのしくみ

アプリケーションを設計するうえで、キャッシュが戦略的選択肢となり得ることがおわかりいただけたと思います。では、キャッシュ サービスとは、実際にどのようなものかをもう少し詳しく見ていくことにします。キャッシュ サービスのさまざまな部分を理解するため、代表的なネット ショッピング Web サイトを例に取り上げます。今回は、Xbox やコンピューター ゲームを販売する e コマース サイトを使用します。

大まかには、次の 3 つが主要部分になります。

  • キャッシュ クライアント
  • キャッシュ サービス
  • キャッシュ クライアントとキャッシュ サービスの接続

キャッシュ クライアントとは、アプリケーション (今回の例ではショッピング Web サイト) 内に常駐するプロキシです。これは、アプリケーションとキャッシュ サービスの双方が正しく理解できる言語で、キャッシュ サービスとの対話方法を把握しているコードです。キャッシュ サービスを発見して対話できるようにするには、このクライアント アセンブリをアプリケーションに含めて、適切な構成で Web アプリケーションに展開する必要があります (この処理については後で説明します)。

キャッシュをそのまま使用できる、ASP.NET セッション状態などの共通アプリケーション パターンがいくつかあるため、クライアントを使用する方法は 2 つあります。

1 つはキャッシュ API に対して明示的にプログラミングを行う方法です。この場合は、SDK からアプリケーションにキャッシュ クライアント アセンブリを含め、GET 呼び出しや PUT 呼び出しを行って、キャッシュにデータを保存したりキャッシュからデータを取得したりすることから始めます。これは、ゲーム Web サイトに、ゲームのカタログやその他の参照データを保存する場合に優れた方法です。

もう 1 つは、さらに高レベルのシナリオでキャッシュを使用する方法です。この場合は、キャッシュ サービス用の ASP.NET セッション状態プロバイダーを含め、キャッシュ API ではなくセッション状態 API を操作する必要があります。セッション状態プロバイダーは、キャッシュ層内のセッション状態を管理するために適切なキャッシュ API を呼び出すという面倒な作業を担います。これは、キャッシュ コードを一行も書くことなく、ユーザー設定、ショッピング カート、ゲームの参照履歴などの情報をセッション状態に保存する場合に優れた方法です。

キャッシュには、テキスト、データ、BLOB、CLR オブジェクトなど、ほぼすべてのオブジェクトを問題なく保持でき、保持するオブジェクトのサイズに制限はありません。したがって、キャッシュに明示的なオブジェクトを格納するつもりでも、セッション状態を格納するつもりでも、アプリケーションからキャッシュ サービスを使用可能にするかどうか決める際、オブジェクトのサイズを考慮する必要はありません。

キャッシュ サービスについて 1 つ注意すべき点は、開発者が明示的に書き込み、完全に制御するキャッシュであることです。キャッシュ サービスは、データベースやストレージの上位に設けられ、開発者が特に意識しなくても利用されるキャッシュ層ではありません。つまり、キャッシュ内で保存および管理するデータを完全に制御できるメリットはありますが、キャッシュを独立したデータ ストアとして、キャッシュ API を使用してプログラミングを行う必要があります。

一般にこのパターンをキャッシュアサイド (cache-aside) と呼びます。このパターンでは、まずキャッシュにデータを読み込みます。その後、データを取得する場合はキャッシュにデータが存在するかどうか確認します。使用可能なデータがキャッシュに存在しない場合のみ、データ層からデータを明示的に読み取ります。このため、開発者としては、キャッシュのプログラミング モデル、API、一般的なヒントやテクニックを理解し、キャッシュを効率よく使用する必要があります。

キャッシュ クライアントについて把握しておくべきもう 1 つの点は、分散キャッシュ サーバーに常駐するデータのサブセットを、クライアント (この例では、ゲームの Web サイトを運用している Web サーバー) に直接キャッシュできることです。一般にこの機能を "ローカル キャッシュ" と呼び、格納するオブジェクトの数と、キャッシュを無効にするタイムアウトの設定を指定する、簡単な構成設定を使って有効にします。

2 つ目の主要部分は、キャッシュ サービスそのものです。キャッシュ サービスとは、マイクロソフトが利用者に代わって運営する大規模キャッシュ クラスターです。マイクロソフトは、パフォーマンス、稼働時間、弾力性、およびスケール アウトの点でこのキャッシュ クラスターに徹底した最適化を行い、利用者が呼び出すエンドポイントを備えた、シンプルなネットワーク サービスとして公開しています。つまり、ユーザーにとっては、管理オーバーヘッドを必要としない、可用性の高いマルチテナント サービスです。

ユーザーとしてのメリットは、対話相手の Windows Communication Foundation (WCF) エンドポイントがセキュリティ保護されること、アプリケーションで使用可能なメモリの量、およびデータの保存と取得のために呼び出すキャッシュ クライアントの API です。ここで重要なのが、使用可能なメモリです。1 GB のキャッシュ メモリを求めると、オブジェクトの保存に使用可能なメモリを 1 GB 入手します。Windows Azure インスタンスで使用可能なメモリ量を購入するのではありません。キャッシュ サービスには、利用者が必要とする量の使用可能なメモリを提供するために運用および管理しているコンピューターの分散クラスターからメモリをプールする役割があります。その結果、構成の簡単な変更だけで、ユーザーのニーズに合わせてキャッシュのサイズを増減できる柔軟性も自動的に提供しています。その意味では、キャッシュ サービスを、パーティション分割された仮想プールかつ柔軟に使用できる共有メモリと考えることができます。

他に理解しておくべき内部設計として、キャッシュ サービスが利用者のキャッシュを自動的にパーティション分割している点が挙げられます。その結果、キャッシュ用に高価な高可用性 (HA) オプションを購入しなくても、コンピューターがダウンするという事態に陥ったときにデータを失うことがなくなります (HA オプションは、現状 Windows Azure AppFabric キャッシュでは使用できず、Windows Server AppFabric キャッシュのみで使用できます)。こうしたパーティション分割方式は、自動的にパフォーマンスを向上し、データ損失の可能性を低減します。利用者が、バックエンド サービスについて学ぶ必要はありません。

最後の 3 つ目の主要部分は、キャッシュ クライアントとキャッシュ サービスとの接続です。キャッシュ クライアントとキャッシュ サービスとの通信には WCF を使用します。ただし、キャッシュ クライアントが GET または PUT 呼び出しを、キャッシュ サービスが理解できる WCF プロトコルに変換するため、開発者にとっては、WCF のプログラミング モデルは抽象化されます。重要なのは、この通信チャネルのセキュリティが確保されることで、これは (クラウドの世界においては特に) きわめて重大です。キャッシュは、(名前付きキャッシュを作成したときに取得する) アクセス制御サービス トークンを使用してセキュリティ保護されます。キャッシュ サービスは、このトークンを使用して、キャッシュされたデータへのクライアントからのアクセスを制限します。

アーキテクチャ ガイダンス

これまでの長い間、さまざまな複雑さのアプリケーションを所有するお客様と関わってきました。通常は、設計上の選択を行ったり、アーキテクチャを検討したりする前に簡単なダイアグラムを描くようにしています (図 1 参照)。多くの場合、このダイアグラムを使って、データの格納と操作にかかわる最も基本的な 3 つの要素のトレードオフを行います (「多くの場合」としたのは、ストレージのエキスパートの中には、ディスク スループットが最大になる前にネットワークが飽和状態になることがあると主張する人がいるためです)。

データの操作シナリオにおけるメモリ、ネットワーク、およびディスクの使用量

図 1 データの操作シナリオにおけるメモリ、ネットワーク、およびディスクの使用量

ローカル コンピューター上のメモリが最も短い待ち時間で最も速くデータにアクセスできるというのが基本原則です。ただし、このメモリの量は、コンピューター上で利用可能なメモリ量の制限を受けます。ローカル コンピューター上で利用可能な量より多くのメモリを必要とする場合、または (共有状態や耐久性を高めるために) コンピューター層からデータを移動する必要がある場合は、すぐに、最低限、ネットワーク ホップという代償を払うことになります。この中で最も代償が少ないのは、ディスクへのデータの格納です (半導体ドライブがやや優位ですが、きわめてコストが高くなります)。

ディスクは最も安価なうえ容量も一番多いのに対し、メモリは一番高価なため、容量の点から最も制約を受けます。キャッシュ サービスは、複数のコンピューター層にまたがる分散メモリや共有メモリの大きなブロックにアクセスするためのネットワーク サービスとしてサービスを提供することで、こうしたさまざまな要素のバランスを取ります。同時に、ローカル キャッシュ機能を使って最適化を行い、ローカル コンピューターにデータのサブセットが追加で常駐できるようにしながら、サービス内のローカル キャッシュとキャッシュ層の間で一貫性を保つという複雑な作業を取り除きます。

このような背景を踏まえて、アプリケーションでキャッシュを使用する際に重要度の高い考慮事項をいくつか見てみましょう。

まず、どのようなデータをキャッシュに配置すべきかですが、これはアプリケーション全体の設計によって大きく異なります。キャッシュのシナリオでデータについて考えるときは、一般に、図 2 のようにデータの種類とアクセス パターンに分けて考えます (これらのデータ アクセス パターンの詳細については、msdn.microsoft.com/library/ee790832 を参照してください)。

図 2 キャッシュのシナリオでのデータ

データの種類 アクセス パターン
参照 共有読み取り
アクティビティ 排他書き込み
リソース 共有、同時読み書き、多数のトランザクションによるアクセス

このモデルを使って考えた場合、(一貫性、強制排出、最新の状態への更新などを管理するために) 容量とアクセス パターンの計画を立て、最も頻繁に使用するデータ、またはアプリケーションから短時間で使用または生成できなければいけないデータだけをキャッシュします。

たとえば、参照データであれば、頻繁にアクセスするデータとあまりアクセスしないデータに簡単にパーティション分割し、キャッシュから参照するか、ストレージから参照するかを分けます。リソース データは、サイズとパフォーマンス上のメリットを最大限に高めるため、以前から、できるだけキャッシュに収めたいデータの例です。キャッシュ層だけでなく、クライアントのローカル キャッシュの使用も、データの種類と密接な関係があります。参照データは、ローカル キャッシュに保存するか、クライアントとキャッシュの両方に配置するのに非常に適していますが、リソース データは、更新が頻繁に行われ、データのやり取りが非常に多くなるため、キャッシュ層に配置するのが最も適しています。

キャッシュ データにアクセスするネットワーク トラフィックのパターンは、特に注意を払う必要があります。ネットワークは、2 番目に高価なリソースであることと、実装の効率が最も悪いことから、通常ボトルネックになるためです。小さなオブジェクトがたくさんあり、こうしたオブジェクトをフェッチする頻度とフェッチするオブジェクトの数を最適化していなければ、アプリケーションは直ちにがネットワークの制限を受けることになります。データのようにフェッチするためにタグを使用したり、頻繁にアクセスする大量の小さなオブジェクトを保持するためにローカル キャッシュを使用したりすることは、優れたトレードオフになります。

名前付きキャッシュに対して HA を有効にするオプションは、キャッシュ サービスではまだ利用できませんが、アプリケーションを設計する際に考慮すべき要素の 1 つです。キャッシュを一時的なキャッシュとしてのみ使用する開発者やアーキテクトがいる一方で、HA 機能を有効にすることで、やみくもにデータ (通常、アクティビティ データ) のサブセットをキャッシュに格納するだけの開発者もいます。HA にはオーバーヘッドがかかりますが、キャッシュをデータの唯一のストアとして扱う設計モデルを提供するため、複数のデータ ストアを管理する必要はなくなります。

しかし、キャッシュはデータベースではありません。今回は、この点をあまり強く主張することはできません。HA を話題にすると、キャッシュでデータ層を置き換えることができると感じることが多いのですが、実際にはまったく違い、SQL データベースは、キャッシュ層の設計とは異なるパターンのセットに対して最適化されています。多くの場合、どちらも必要であり、組み合わせて使用することで、コストを抑えつつ最高のパフォーマンスとアクセス パターンを実現することが可能になります。

キャッシュをデータの集約に使用することについてはどうでしょう。これは強力なのに、通常見落とされることが多いシナリオです。クラウドでは、アプリケーションはさまざまなソースからのデータを扱うことが多く、データは、集約するだけでなく正規化することも必要です。(読み書きをディスクではなくメモリ内で行う) スループットの高い正規化を行って、このような集約データを格納および管理する場合、キャッシュは、効率が良くパフォーマンスの高い代替手段となります。キーと値のペアを使用して正規化したデータをキャッシュに保持する構造は、集約データを保存および管理する方法として優れた考え方です。

アプリケーションの開発者とアーキテクトが対処すべき共通の問題は、前回の要求を処理したのと同じサーバーにクライアントが常にルーティングされる保証はない点です。このようにセッションを固定できないときは、このような状況に対処するため、セッション状態に何を保存するかと、サーバー間で要求をどのようにやり取りするかを決める必要があります。キャッシュは、複数のコンピューター ノード間の共有状態を保持する非常に魅力的な代替手段になります (今回の例では、これらのノードは Web サーバーですが、コンピューター層間で情報を共有するシナリオには同じ問題が当てはまります)。すべてのクライアントがアクセスするため、キャッシュ層が共有状態を自動的に一貫して管理します。キャッシュ層では、ディスク (データベースやファイル) に書き込むオーバーヘッドや待ち時間が生じません。

ここで考慮すべきトレードオフは、(リアルタイムにスコアを付けるオンライン ゲームの Web サイトでのセッション状態のように) ほとんど待ち時間なく共有状態にアクセスする必要がある場合は、外部キャッシュ層が最適なオプションではなくなるという点です。それ以外のほとんどのシナリオでは、キャッシュ層を使用することが、この設計パターンに対処する高速かつ強力な方法であり、データが古くなることが自動的になくなります。

キャッシュの容量計画の立案には十分な時間をかけてください。オブジェクトの数、各オブジェクトのサイズ、各オブジェクトのアクセス頻度、およびこれらのオブジェクトにアクセスするパターンはすべて、アプリケーションに必要なキャッシュの数を判断するときだけでなく、どの層を最適化するか (ローカル キャッシュ、ネットワーク、キャッシュ層、領域とタグの使用など) について判断するときにも重要です。キャッシュを使用するソリューションを最も効率的な方法で設計するには、コードをまったく記述せずにキャッシュを使い始めるために web.config ファイルの簡単な構成スイッチから始め、そこから何年もかかることを覚えておいてください。

AppFabric キャッシュをセットアップする

Windows Azure AppFabric キャッシュを使い始めるには、portal.appfabriclabs.com (英語) にアクセスします。このサイトは、キャッシュ サービスについて知ることができる CTP ポータルです。まったく無償ですが、キャッシュ サービスのサービス レベル契約はありません。

このポータルで [Cache] (キャッシュ) オプションを選択し、[New Namespace] (新しい名前空間) をクリックして新しいキャッシュを作成します。図 3 は、キャッシュ サービス名前空間を構成するダイアログ ボックスです。

新しいキャッシュ サービス名前空間の構成

図 3 新しいキャッシュ サービス名前空間の構成

指定する必要があるオプションは、一意のサービス名前空間とキャッシュのサイズ (CTP 版では、128 MB と 256 MB のいずれかを選択できます) の 2 つのみです。[OK] をクリックすると、サービスが、バックグラウンドでキャッシュをプロビジョニングします。通常、これには 10 ~ 15 秒かかります。完了すると、アプリケーションから完全に機能する分散キャッシュを使用できるようになります。

キャッシュが作成されたら、キャッシュのプロパティを確認できます (図 4 参照)。ここではアカウント固有の情報をいくつか意図的に不鮮明にしています

キャッシュ サービスのプロパティ

図 4 キャッシュ サービスのプロパティ

このキャッシュは、CachingDemo 名前空間を使用して作成したことがわかります。ここには、この後コードで使用するために把握しておくべき情報として、サービス URL と認証トークンも表示されます。サービス URL は、キャッシュ サービスを操作するときにアプリケーションから接続する TCP エンドポイントです。認証トークンは、サービスを認証するためにアクセス制御に渡す、暗号化されたトークンです。

アプリケーションでキャッシュを行う

コーディングを開始する前に、Windows Azure AppFabric SDK をダウンロードします。go.microsoft.com/fwlink/?LinkID=184288 (英語) にアクセスするか、ポータルのリンクをクリックします。

コンピューターに Windows Server AppFabric キャッシュをインストールしていないことを確認してください。API には対称性がありますが、現時点ではアセンブリに互換性はありません。Windows Server AppFabric キャッシュは、グローバル アセンブリ キャッシュ (GAC) に自身のキャッシュ アセンブリを登録するため、アプリケーションは誤ったアセンブリを読み込みます。この問題は、キャッシュ サービスが運用環境に導入されるころには解決する予定ですが、現状は少しだけ摩擦を引き起こします。

まず、C# を使用して、簡単なコンソール アプリケーションを作成します。作成したら、プロジェクトを更新して、クライアント プロファイルではなく完全な Microsoft .NET Framework をターゲットにします。また、通常 C:\Program Files\Windows Azure AppFabric SDK\V2.0\Assemblies\Cache にある、キャッシュのアセンブリを追加することも必要です。現状では、次の 2 つのアセンブリを追加します。

  • Microsoft.ApplicationServer.Caching.Client
  • Microsoft.ApplicationServer.Caching.Core

10 月の CTP 版から 2 月の更新版に向けての変更点の 1 つは、認証トークンに System.Security.SecureString を使用しなけれなならなくなった点です。SecureString の目的は、アプリケーションのメモリ内にパスワードやトークンを保持する必要をなくすことなので、より安全性が高まります。ただし、これを簡単なコンソール アプリケーションで機能させるには、次のようなメソッドを作成する必要があります。

static private SecureString Secure(string token) {
  SecureString secureString = new SecureString();
  foreach (char c in token) {
    secureString.AppendChar(c);
  }
  secureString.MakeReadOnly();
  return secureString;
}

このコードでは強制的にトークンをメモリに読み込ませているため、SecureString の目的に意味がなくなりますが、上記のメソッドを使用するのはこのようなシンプルなシナリオの場合のみです。

次に、キャッシュ サービスを操作するためにセットアップするコードを記述します。API はファクトリ パターンを使用するため、ファクトリを定義し、構成設定をいくつか設定してから、既定のキャッシュを読み込みます (図 5 参照)。

図 5 既定のキャッシュを読み込む

private static DataCache configureDataCache(
  SecureString authorizationToken, string serviceUrl) {

  // Declare an array for the cache host 
  List<DataCacheServerEndpoint> server = 
    new List<DataCacheServerEndpoint>();
  server.Add(new DataCacheServerEndpoint(serviceUrl, 22233));

  // Set up the DataCacheFactory configuration
  DataCacheFactoryConfiguration conf = 
    new DataCacheFactoryConfiguration();
  conf.SecurityProperties = 
    new DataCacheSecurity(authorizationToken);
  conf.Servers = server;

  // Create the DataCacheFactory based on config settings 
  DataCacheFactory dataCacheFactory = 
    new DataCacheFactory(conf);

  // Get the default cache client 
  DataCache dataCache = dataCacheFactory.GetDefaultCache();

  // Return the default cache
  return dataCache;
}

ポート 22233 を指す (今回提供する) サービス URL に基づいて新しい DataCacheServerEndpoint を定義しています。次に、DataCacheFactoryConfiguration を作成し、認証トークン (SecureString) に渡してセキュリティ プロパティに設定します。これにより、サービスを認証できるようになります。この時点では、単に DataCacheFactory を構築して、既定のキャッシュに基づいて DataCache を取得し、既定のキャッシュを返しているだけです。

このロジックを独自のメソッドにカプセル化することは必須ではありませんが、カプセル化しておけば後から便利になります。

この時点では、これをアプリケーションの Main メソッドにまとめるのはかなり簡単です (図 6 参照)。

図 6 コンソール アプリケーションの Main メソッド

static void Main(string[] args) {
  // Hardcode your token and service url
  SecureString authorizationToken = 
    createSecureString("YOURTOKEN");
  string serviceUrl = "YOURCACHE.cache.appfabriclabs.com";

  // Create and return the data cache
  DataCache dataCache = 
    configureDataCache(authorizationToken, serviceUrl);

  // Enter a value to store in the cache
  Console.Write("Enter a value: ");
  string value = Console.ReadLine();

  // Put your value in the cache
  dataCache.Put("key", value);

  // Get your value out of the cache
  string response = (string)dataCache.Get("key");

  // Write the value
  Console.WriteLine("Your value: " + response);
}

ここでは、アプリケーションに認証トークンとサービス URL を提供し、それらを configureDataCache メソッドに渡しました。これにより、DataCache 変数が既定のキャッシュに設定されます。ここから、なんらかの入力をコンソールから取得して、キャッシュに配置します。その後、キーを指定して Get を呼び出せば、値が返されます。実に簡単ですが、有効なキャッシュのテストです。

コードにトークンやサービス URL を含めることは、あまり好ましくはありません。さいわい、ポータルでは app.config (または web.config) ファイルに挿入できる XML が提供され、API がすべてを管理してくれます。

ポータルで、キャッシュを選択して [View Client Configuration] (クライアント構成を表示する) ボタンをクリックします。これにより、構成 XML を提供するダイアログ ボックスが開きます。XML スニペットをコピーして、構成ファイルに貼り付けます。この結果、図 7 のようになります。

図 7 クライアント構成

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section 
      name="dataCacheClient" 
      type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core" 
      allowLocation="true" 
      allowDefinition="Everywhere"/>
  </configSections>
  <dataCacheClient deployment="Simple">
    <hosts>
      <host 
        name="YOURCACHE.cache.appfabriclabs.com" 
        cachePort="22233" />
    </hosts>
    <securityProperties mode="Message">
      <messageSecurity
          authorizationInfo="YOURTOKEN">
      </messageSecurity>
    </securityProperties>
  </dataCacheClient>
</configuration>

これでコードを大きくリファクタリングして、createSecureString メソッドと configureDataCache メソッドを取り除くことができるようになります。

static void Main(string[] args) {
  DataCacheFactory dataCacheFactory = 
    new DataCacheFactory();
  DataCache dataCache = dataCacheFactory.GetDefaultCache();
  Console.Write("Enter a value: ");
  string value = Console.ReadLine();
  dataCache.Put("key", value);
  string response = (string)dataCache.Get("key");
  Console.WriteLine("Your value: " + response);
}

DataCacheFactory の新しいインスタンスを作成するだけで、app.config ファイルにおけるすべての構成設定が既定で読み込まれることがおわかりいただけると思います。

このように、API を直接使用することも、構成で DataCacheFactory を管理することも可能です。ここでは、簡単なデータに対して PUT 操作と GET 操作を行っただけですが、SQL Azure、Windows Azure、およびその他のデータのプロバイダーから取得したデータを格納することも容易です。SQL Azure に格納されているデータを参照するキャッシュを使用する方法の詳細については、Windows Azure Platform トレーニング コースのキャッシュ サービス ハンズオン ラボ (msdn.microsoft.com/gg457894、英語) を参照してください。

セッション データを格納する

次に、キャッシュ サービスを使用して、ASP.NET Web アプリケーションのセッション データを格納する方法について見ていきます。これは、各 Web クライアントのプロセス内のメモリからセッション状態を切り離す強力な手法となるため、Windows Azure 内でアプリケーションを複数のインスタンスにスケール変換するのが容易になります。

このことは、Windows Azure など、セッションが固定されないサービスにとっては重要です。ユーザーが新たに要求を行うたびに、各要求が同じインスタンスで処理されることは保証されません。実際、Windows Azure ロード バランサーは、ラウンドロビン方式で明示的に負荷分散を行うため、要求が新しいインスタンスで処理される可能性の方が高くなります。セッション状態の格納にキャッシュ サービスを使用すると、同じセッション状態プロバイダーがすべてのインスタンスをサポートすることになるため、要求がどのインスタンスで処理されても問題なくなります。

まず、新しい Windows Azure プロジェクトを作成して、ASP.NET Web ロールを追加します。Web ロールでは、以下のアセンブリを含め、Windows Azure AppFabric SDK から提供されるアセンブリをすべて追加します。

  • Microsoft.ApplicationService.Caching.Client
  • Microsoft.ApplicationService.Caching.Core
  • Microsoft.Web.DistributedCache
  • Microsoft.WindowsFabric.Common
  • Microsoft.WindowsFabric.Data.Common

次に、<configuration> 要素の直後に <configSections> 要素と <dataCacheClient> 要素がくるように、web.config ファイルを更新します (これらを最初の要素にしないと、エラーが発生します)。

セッション状態にキャッシュ サービスを使用する際に鍵となるのは、Microsoft.Web.DistributedCache アセンブリです。これには、キャッシュ サービスを使用するカスタム セッション状態プロバイダーが含まれています。構成ファイルの XML を取得した LABS ポータルに戻り、<sessionState> 要素を探します。これを、web.config ファイルの <system.web> 要素に直接追加すると、セッション状態にキャッシュ サービスを使うようアプリケーションに即座に指示することになります。

<system.web>
  <sessionState mode="Custom" 
    customProvider="AppFabricCacheSessionStoreProvider">
    <providers>
      <add name="AppFabricCacheSessionStoreProvider"
        type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"
        cacheName="default"
        useBlobMode="false" />
    </providers>
  </sessionState>
  ...
</system.web>

これが機能することを検証するには、Global.asax.cs ファイルを開いて、次のコードを Session_Start メソッドに追加します。

void Session_Start(object sender, EventArgs e) {
  int i = 0;
  while (i < 10) {
    Session.Add(Guid.NewGuid().ToString(), DateTime.Now.ToString());
    i++;
  }
}

これにより、ランダムな 10 個のアイテムが、セッション コンテキストに追加されます。次に、Default.aspx.cs ページを開いて、次のように Page_Load メソッドを更新します。

protected void Page_Load(object sender, EventArgs e) {
  foreach (var key in Session.Contents) {
    Response.Write("key: " + key + ", guid: " + 
      Session[key.ToString()].ToString()  + "<br/>");
  }
}

これにより、セッション コンテキストに追加されたすべての値が出力されます。最後に ServiceConfiguration.cscfg ファイルを開いて、インスタンス数を 1 から 2 に増やします。

<Instances count="2" />

ここで F5 キーを押すと、Compute Emulator で実行されているアプリケーションのインスタンスが 2 つになります。ページを何度更新しても、セッション状態には同じ 10 という値が常に表示されます。これは、セッションが共有セッションで、セッションの開始が一度しか実行されないためです。逆に、セッション状態プロバイダーとしてキャッシュ サービスを使用しないで、プロセス内でのセッションの選択をそのまま使用すると、各インスタンスは異なる値を取得することになります。

今後の展望

Windows Azure AppFabric キャッシュ サービスは、2011 年上半期に商用サービスとして運用環境に導入される予定です。最初の商用リリースでは、Windows Server AppFabric 機能の一部を使用できません。そのうちのいくつかは、クラウド環境にそぐわないため意図的に使用できなくされています。ただし、通知などの機能は Windows Azure にも関連していて、ローカル キャッシュのシナリオを完成するのに重要なので、マイクロソフトの短期ロードマップに含まれています。同様に、特定の名前付きキャッシュに HA を有効にするプレミアム オプションは、優先順位の中でも上位に位置しています。

Windows Server AppFabric キャッシュの利用が広がっているため、多くの新機能が要望され、さらに大規模なシナリオにキャッシュを利用できる可能性が高まっています。議論されているいくつかの機能の中には、キャッシュで豊富なクエリを実行して、名前付きキャッシュから膨大なデータを簡単に取得できるようにする機能などがあります。

さらに、ASP.NET でのキャッシュ セッション状態プロバイダーの成功により、キャッシュがデータ操作の主要方法になれるように、write-behind/read-through クエリをキャッシュと関連付け、同時に、関連しているクエリがバックエンドでデータ層を更新するという機能も求められるようになりました。

今後も、Windows Azure AppFabric キャッシュのリリースに含められる、このような機能を評価していく予定です。それまでは、最新のキャッシュ サービスの実装をテストして、どのように役立ったかを教えていただければ、さいわいです。

Karandeep Anand は、マイクロソフトの AppFabric 製品グループのプリンシパル グループ プログラム マネージャーです。彼のチームは、Windows Azure Platform および Windows Server 向けに次世代アプリケーション プラットフォームとサービスを構築しています。連絡先は Karandeep.Anand@microsoft.com (英語のみ) です。

Wade Wegner は、マイクロソフトのテクニカル エバンジェリストとして、Windows Azure Platform に関するマイクロソフトの技術戦略の普及および推進を担当しています。彼の連絡先は、ブログ (wadewegner.com、英語) または Twitter (twitter.com/WadeWegner、英語) です。