特集:クライアントステート管理、3つの手法Visual Studio Magazine(5/9 ページ)

» 2004年12月28日 10時30分 公開
[Matthew Gibbs, Rob Howard,FTPOnline]

Webサーバファームでセッションデータを構成する

 アウトプロセスセッションの有利な点は、クライアントとサーバーとの密接な結び付きがもはや要求されなくなるということだ。

 ASP.NETでWebサーバファームを構成するサーバー群は、セッションデータを共有するように構成できる(しかしセッションはアプリケーションごとに結び付けられるため、アプリケーション間でセッションデータを共有することはできない)。

 Webサーバファームでセッションをサポートするには、セッションが実際に使われるかどうかに関わらず、ひとつの追加手順が必要となる。それは、machineKey設定の構成だ。

 マシン全体に渡る設定は、machine.configファイル(WindowsディレクトリのMicrosoft.NET\Framework\バージョン\Configディレクトリに存在する)を使って構成できる。machineKey設定には、validationKey属性とdecryptionKey属性が含まれる。これらの設定値は、ViewStateやフォーム認証、セッションなど、クライアントからサーバへと送受信される値の、暗号化や検証のために多くの場面で使われる。

 validationKeyとdecryptionKeyの属性は、標準では「AutoGenerate」に設定される。この場合、サーバはランダムな値を作成する。

 ランダムに作成された値は、単一のサーバーで構成する場合には、うまく機能する。しかし、クライアントからのリクエストをどのサーバが処理するのかを確定しないWebサーバファーム環境では、validationKeyとdecryptionKeyに対する値は、正確に決まったものでなければならない(訳注:全HTTPサーバにおいて、validationKeyとdecryptionKeyをそれぞれ固定された同じ値を使うように構成する必要がある)。

 アウトプロセスのセッションを利用する場合、ASP.NETは、誰かがページを要求する場合に、アウトプロセスの状態ストア(訳注:State ServerやSQL Server)に対し、2つのリクエストを生成する(クライアントからのリクエストにSessionIDが含まれている場合)。リクエストが開始された際、セッション状態モジュールは、状態ストアに接続し、セッション状態のデータを読み、そのセッションが「ロックされた」という印を付加する。この時点でページは実行され、Sessionオブジェクトがアクセス可能になる。

 ページ実行が終わると、セッション状態モジュールは状態ストアに接続し、状態データが変化していれば、それを書き込む。そして、セッションデータのロックを解除する。実装されているロックの仕組みは、ReaderWriterLockクラスを用いた読み書きロックだ。

 なお、セッションがロックされなければ、複数のリクエストは同時にデータを読み取ることができる。セッションがロックされている場合には、書き込みロックが解除されるまで、読み取りリクエストはブロックされ、待たされる。このロック機構によってSessionオブジェクトは、常に正しいデータを映し出していることが保証される。

 フレームを利用するサイトを構築する場面では、フレームに含まれるページがそれぞれセッション状態を要求すれば、(訳注:セッションのロックが解除されるまで待つことになるから)ページは並行実行できず、1ページずつの順次実行になってしまう。セッション状態は、ページ単位やアプリケーション単位で、読み取り専用にすることができる。

 ページに対してセッション情報を読み取り専用にすると、セッションデータにロックをかけることなくページがリクエストを受け付けられるようになり、順次でしか実行できないという問題を解決できる。また、アウトプロセスモードにおいて、セッションが読み取り専用として構成される場合、セッションモジュールは、ロックを解除するために状態ストアに再接続する必要もなくなる。複数のリクエストが発生しても順次アクセスされる必要がなくなるので、待たされることなくセッションデータを同時に読むことができる。その結果、良いスループットを産み出せる。

 ページ単位で読み取り専用オプションを構成するには、ページレベルのディレクティブであるEnableSessionStateを用いる。

<%@ Page EnableSessionState="ReadOnly" %>

 ほかに、(web.configファイルやmachine.configファイルを変更することによって)「enableSessionState="false"」としてデフォルト設定を変更しておき、ページレベルで「EnableSession="ReadOnly"」や「EnableSessionState="true"」と指定する方法もある。次のコードは、セッション状態を無効にするものだ。

<configuration>
<system.web>
<pages enableSessionState="false" />
</system.web>
</configuration>

 アウトプロセスのセッションにおいては、セッション状態を構成ファイルで「enableSessionState="false"」としておき、セッションの書き込みが必要か否かによって、pageディレクティブ(@Page)でEnableSessionStateをtrueまたはReadOnlyにする。

 ここでfalseに設定されている場合でも、セッションタイムアウト時間がリセットされる点に注意してほしい。アウトプロセスのセッションでは、この方法を適用することによって状態ストアへのリクエストを少なくでき、サイトのスケーラビリティ、そしてスループット向上が見込める。

 HTTPプロトコルの純粋な信者は賛同しないだろうが、セッション状態は、実世界のWebアプリケーションを構築する場合に不可欠な機能だ。セッション状態は、HTTPのステートレスな世界の制限の元で、動作することを目指したものだ。ブラウザとサーバは、共通な一片のデータを共有しなければならない。それはSessionIDだ。この共有される値は、どこかに保存される必要がある。クッキーとして知られるHTTPの拡張機能を利用することで、この問題は解決される。すべてのブラウザでサポートされる非常によく考えられた機能だ。クッキーは、サーバがクライアント上で少量のデータを保存できるようにする。クライアントがサーバにリクエストを要求するたびに、ブラウザは、クッキーを通じて、該当するサーバに属するデータを送り込む。

 ASP、ASP.NETであっても、SessionIDはクッキー内に格納される。クライアントがサーバにリクエストする場合、クライアントはASP.NETに対し、SessionIDに属するセッションデータに付随するデータを取り出す機会を与えるクッキーを提示する。SessionIDをユーザーデータのキーとして使うことは推奨されない(訳注:これは、SessionIDはその瞬間においてほかのユーザーと重複しない値であり、サーバを再起動したり、時の経過で同じSessionIDが再利用される可能性もあるためだ)。また、SessionIDはランダムに作成される。そしてセッションデータは、SessionIDとともに期限切れになる。

 なお、SessionIDは各リクエストで生成される可能性があるが、サーバ側でセッションに値を設定した場合に限って、SessionIDが設定される。これは、サーバ側でセッションに値を設定しない場合には、リクエストのたびに新しいSessionIDが発行されるということを意味する。

 クッキーにSessionIDを保存する方法は、クライアントがクッキーを拒否しない限り、うまく機能する。ただし、サポートされない場合のために、ASP.NETはクッキーの代わりにURLへSessionIDを保存するというオプションを提供している。

 ASP.NETのWebアプリケーションにおいて、SessionIDを保存する方法として「クッキー」と「クッキーなし」の両方をサポートするように構成することはできず、動的にクッキーを使うか否かを選べない。このため、クッキーなしのセッションを使ってアプリケーションを構築する場合、ユーザーインタフェースのナビゲーションを注意深く設計しなければならない。

 サイト内の相対的ではないリンク(http://で始まるもの)がクリックされた場合には、セッションを失う結果となる。相対的なURL(たとえば/MyStore/default.aspx)においては、ASP.NETは、ページ出力を生成する時にそのURLにSessionIDを自動的に埋め込む。

© Copyright 2001-2005 Fawcette Technical Publications

注目のテーマ