Windows Server AppFabric (Cache Services) の入門


最新の Redis Cache については「Azure Redis Cache の使用 (.NET, PHP, Node.js)」に記載しました。(以降は、古い記事です)

環境 : Visual Studio 2010 (.NET Framework 4), Windows Server AppFabric

Windows Server AppFabric 入門

関連ナンバー

こんにちは。

Tech Ed 2010 の予習として、コードネーム Velocity と呼ばれていた Windows Server AppFabric のキャッシュサービス (Cache Services) の超入門を記載します。(冗長な余談はいっさい書きません。。。)
なお、ホスティングサービス (コードネーム Dublin) のほうは、以前このブログで記載していますので、上記のリンクを参考にしてください。(今回、このホスティングサービスの内容も RTM 用に書き換えました。)

 

キャッシュサービス (Velocity) とは何者か?

まず、このキャッシュ サービスって何でしょうか?

これは、いわゆるインメモリ データの分散キャッシュ技術と呼ばれるもので、アプリケーションの中で扱うインメモリ データに対して莫大なスケーラビリティが必要とされるようなケースや、データベースへの負荷を減らしながらデータ アクセスの高速化をおこなうようなケースで使用するテクノロジです。(現時点では、データベースのような永続化データを扱う仕組みは持っていません。)
アプリケーション側 (ASP.NET MVC アプリケーションなど) からは、「分散」を意識することなく、ローカルのメモリー上のデータのように扱うことができ、データの分散・同期は、キャッシュ サービス (コードネーム Velocity) に任せることができます。(ただし、後述するように、プログラム側は、Velocity を強く意識した書き方になるので、現状は、ラッピングするなどの工夫が必要です。)
図示すると、以下のようになります。下図で、Caching Tier のサーバーを自由に増やしていくことで、スループットの向上を実現できます。

そこまでしてスケーラビリティをあげるようなケースは想像しずらいかもしれません。データベースの能力は決して低いわけではありません。一般のシステムなら、データベースだけでも充分でしょう。しかし、例えば、Amazon (コマース系) とか、Yahoo みたいな、あのような膨大なトラフィックを処理するサイトを構築・運営するようなケースを想像してみてください。こうした場合の多くは、こうした技術、もしくは、これに代わる類似の技術が必要とされます。ひとたびデータ層のアクセスで遅延が発生すると、引き続く膨大な処理によって、そのボトルネックはすぐに蓄積され、システム全体に甚大な影響を及ぼすことでしょう。
なお、どこで使っているのか私は知りませんが、米国の Tech Ed 2010 North America のセッションによると、Windows Azure の内部でも、この Velocity で採用されている分散アルゴリズムが使われているらしいです。(要は、実地検証を経た、オスミツキの技術、というわけです。)

 

インストール

Windows Server AppFabric のダウンロードについては、前回の ホスティングサービスの入門 を参照してください。

Velocity のインストールでは、まず、キャッシュの構成情報を保持するための専用のデータベースを準備します。(推奨されていませんが、データベースを使用せずファイルに構成情報を保持することも可能です。) ホスティングサービスの入門 のときに述べた要領で、SQL Server 上に空のデータベースを作成し、適当に権限を付与しておいてください。

【注記】 このデータベースは、上述の通り、構成情報の共有のために使用しています。Cache Tier で扱うインメモリデータがここに保持されるわけではありません。

Windows Server AppFabric のインストールをはじめると、インストールする機能を選ぶ画面が出てくるので、今回は、キャッシュサービスとキャッシュクライアントの両方を入れてしまいましょう。(すみません、下図は、もうインストール済みの環境で機能画面を出していますので、もしかしたら、実際は違う画面かもしれませんが。。。)

前述のアーキテクチャ図 (というほどちゃんとした図ではないですが。。。) の通り、Caching Tier に相当するサーバー部分と、そこに接続するクライアント部分 (Web Tier) のインストールは、通常は、別々におこなうことになるでしょう。今回は、超入門!ということで、両方を同じマシンに入れてしまいます。(なお、サーバー側は .NET 4 が必須ですが、クライアント側は、実は、.NET 3.5 も可能です。すみません、余談でした。。。)

インストール後の構成画面では、クラスタやキャッシュの構成情報を保存 (共有) するためのデータベース (またはファイル) を指定する画面が出てくるので、ここで、上記で作成しておいた SQL Server のデータベースを指定します。

注意点があるとすれば、インストール時に、Windows ファイアウォールを無効にしないことです。上記のアーキテクチャ図の通り、Web Tier と Caching Tier の間での通信や、Caching Tier の中のサーバーどうし (クラスター間) の通信など、ネットワーク接続をおこなうためにいくつかのポートが開いていなければいけません。Windows の既定の設定では、Windows ファイアウォールによって、ポートはバリバリ閉じてしまっていますが、インストール時に、これらの必要なポートを開けてくれます。(開けるかどうかチェックする画面が出てきます。) インストール時に Windows ファイアウォールを無効にすると、この「ポートを開ける」という設定をおこなえないので、あとから Windows ファイアウォールを有効にした際に、分散キャッシュが動かなくなってしまうので注意してください。
(ただし、Windows ファイアウォールを有効にした場合には、SQL Server のポートを開けるのを忘れないようにしてください。詳細は こちら に記載しています。)

Velocity で使用するポートの既定値は以下の通りです。(既定値は、インストール時や、インストール後などに変えることができます。)

キャッシュポート : 22233

クラスターポート : 22234

判別ポート  : 22235

レプリケーションポート : 22236

【注記】 なお、2 台目以降のサーバーをクラスターに追加する場合は、インストール後の構成画面で、[クラスターに参加] を選択して、[AppFabric キャッシュサービス構成データベースを登録する] のみを選択し、既存の構成データベースを選択してください。([AppFabric キャッシュサービス構成データベースを作成する] は、最初の 1 台目の構成データベースの作成時のみに選択します。)
この際も、当然のことながら、忘れずに、接続先の SQL Server 側で、リモート接続の設定 (リモート接続の許可、データベースサービスの TCP/IP プロトコル設定、SQL Server Browser サービスの設定、Windows ファイアウォールの設定、など) をおこなっておいてください。

 

キャッシュの設定とクラスターの起動

では、実際にこのインストールしたキャッシュサービスを使って、プログラミングをしてみましょう。

と、その前に、いくつかの設定をしておかないと使えません。

サーバー上 (Windows) で、[すべてのプログラム] - [Windows Server AppFabric] - [Windows PowerShell のキャッシュ管理] を選択すると、キャッシュ管理用の PowerShell コンソールが起動してきますので、これを使って管理をおこないます。

補足 : あるいは、普通に PowerShell を立ち上げて、

import-module distributedcacheadministration

use-cachecluster

と入力しても構いません。

補足 : 使用可能なキャッシュ関連のコマンド一覧は、下記で確認できます。

get-command -module distributedcacheadministration

まず、キャッシュにアクセス権を設定します。
既定のアクセス権 (セキュリティ) では、誰もアクセスできない状態ですから、以下の通り実行して、ユーザーに権限を付与します。下記で、「domain\user」 の箇所は、実際にキャッシュにアクセスするユーザー (アプリ側からアクセスするユーザー) を指定してください。特に、IIS 上でキャッシュクライアントを使用する場合は、アプリケーションプールの ID (アカウント) にアクセス権を付与しないといけないので、要注意です。(なお、DMZ の中で構成する場合など、このセキュリティが邪魔な場合は、アクセス権自体をオフにすることもできます。う~ん、どうしても余談を書いてしまう。。。)

Grant-CacheAllowedClientAccount domain\user

そして、クラスターを起動します。以下の通り入力します。(クラスターに複数台のサーバーがある場合は、すべてのサーバー上のサービスが起動します。)

start-cachecluster

さいごに、「キャッシュ」 (入れ物) を作成しないといけません。このコンソール上で、

new-cache HogeHoge

と入力すると、「HogeHoge」という名前のキャッシュが作成されます。(作成したキャッシュを確認するには、get-cache と入力します。)

 

キャッシュサービスを使ったプログラミング

ということで、準備完了です。

キャッシュのクライアント側で (といっても、今回はサーバーとクライアントが同じマシンですが)、Visual Studio 2010 のプロジェクトを新規作成し、キャッシュを使用するため、以下の 2 つのアセンブリを参照追加します。(ここで、「Sysnative」と記載している点に注意してください。実際には system32 フォルダの下に入っていますが、64 bit 環境のマシンの場合、Visual Studio 自身が 32 bit ですので、リダイレクト によって syswow64 に飛ばされてしまうためです。)

%windir%\Sysnative\AppFabric\

Microsoft.ApplicationServer.Caching.Core.dll

Microsoft.ApplicationServer.Caching.Client.dll

なお、今回は、ASP.NET の Web アプリケーションのプロジェクトを新規作成しますが、Client Profile では使用できないので、コンソールアプリケーションなどで試す際には注意してください。(Client Profile でないプロジェクトに変換して使用します。)

つぎに、プロジェクトの構成ファイル (web.config) を開き、下記の太字部分を追加します。
ここでは、使用するキャッシュサービスを 1 台設定 (マシン名とポート番号を設定) しています。(なお、どれか 1 台でも設定しておけば Cache Tier 全体のキャッシュ (サーバー上に分散されたすべてのキャッシュ) を使用できます。動作の詳細は、ここでは省略します。。。)

<configuration>
  <configSections>
    <section name="dataCacheClient"
          type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </configSections>
  <dataCacheClient>
    <hosts>
      <!-- 使用するキャッシュサービスを列挙 (今回は1台) -->
      <host name="localhost" cachePort="22233"/>
    </hosts>
  </dataCacheClient>
  . . .

Default.aspx.cs に、以下のコードを記述します。

. . .
using Microsoft.ApplicationServer.Caching;

protected void Page_Load(object sender, EventArgs e)
{
    var factory = new DataCacheFactory();
    var cache = factory.GetCache("HogeHoge");
    var test = cache.Get("Foo"); // cache["Foo"] でも良い
    if (test == null)
    {
        cache.Add("Foo", "test"); // ここも、cache["Foo"] という方法で書けます
        test = "test (new !)";
    }
    Label1.Text = (string)test;
}

以上、プログラムの作成完了です。上記のコードの通り、Get/Put/Add/Remove を主体とした、Key-Value 型のデータアクセスになります。

【注記】 実際の開発では、上記のように、ページがロードされるたびにファクトリー (DataCacheFactory) の作成を毎回おこなうことは避けたほうが良いでしょう。(オーバーヘッドの原因となります。static 変数などを使用して保持しておくと良いでしょう。) 上記は、サンプル コードとして記載しています。

実行すると、初回は、ラベルに「test (new !)」と表示され、2 回目からは (ページのリロードなどをおこなうと)、メモリ中にロードされたキャッシュデータが使用されるので、「test」と表示されます。
上記はサンプルとして文字列「test」を設定していますが、任意の .NET オブジェクトを入れられますので、単一の値だけでなく、付帯情報なども自由に扱うことができます。(インメモリデータですので、シリアライズ可能でないオブジェクトも扱えます。 2010/08 訂正 : すみません!ここ、誤りです。シリアライズ可能なデータを扱います。)

ちなみに、PowerShell で、以下の通り実行すると、キャッシュクラスターが再起動されるので、上記のキャッシュはすべてクリアされ、ページを表示すると、また「test (new !)」と表示されるはずです。(ただし、15 秒程度待ってから実行してください。。。)

restart-cachecluster

 

ところで、中でどうやって動いてるんでしょうね? 一貫性ってちゃんと保たれるんでしょうか? キャッシュデータの内容って、いつ消えるんでしょう? Azure ストレージのテーブルストレージのようにパーティションって作れないんでしょうか? 可用性って維持されるんでしょうか? セキュリティはどういう考え方なんでしょう? ASP.NET の Session も似たことができますよね? Web サーバーの出力キャッシュとの関係も気になりますね? ADO.NET Entity Framework などのセカンドレベルキャッシュとして扱えないのでしょうか? Azure 上での対応は? 並列の計算ってどうするの? . . . う~ん、知れば知るほど、いろいろ気になりますね。。。

 

Comments (0)

Skip to main content