Open棟梁Project - マイクロソフト系技術情報 Wiki

目次

概要

はじめに

Webシステムの状態管理方式

2層C/Sシステムでは、クライアント側プログラムがDBに直接接続し、状態(UPが処理に必要とする一連の情報(制御情報や業務処理に必要な情報を含む))を一元管理するという方式が採用されている。これに対し3層C/SシステムやWebシステムでは、APサーバの拡張性・信頼性を確保するために、サーバの状態を保持しないで「サーバへのリクエスト」・「クライアントへのレスポンス」の間で必要な情報を持ち回り、サーバがリクエストを受け付けたときサーバ側で状態を復元するという方式が一般化した(一般的に、サーバに状態を保持しないほうが拡張性は高くなる(サーバに状態を保持した場合、信頼性を確保するための冗長化構成が組み難いなどの問題があるため))。しかし、近年のWebシステムにおいては、サーバに状態を保持した場合も拡張性・信頼性を確保するための技術(Session情報をリモート プロセス・リモート サーバなどで一元管理するためのインフラス トラクチャの構築技術)も登場しており、サーバ側のメモリ領域にユーザ毎に確保される「Session」を使用して、状態を保持するケースが多数を占めるようになってきている。このため、3層C/SシステムやWebシステムの「状態管理方式」の大枠は、次の2つの方式に分けることができる。

表1:3層C/SシステムやWebシステムの状態管理方式

項番状態管理方式説明
サーバ ステートレスサーバ側の状態保持領域を利用しない。
サーバ ステートフルサーバ側の状態保持領域を利用する。

特にWebシステムの「状態管理方式」は、クライアント側で状態を一元管理することができないため、クライアント側とサーバ側の双方で連携して状態を管理する必要があり、2層・3層C/Sアプリケーションと比べて複雑である。このため、本ドキュメントではWebアプリケーション用のAPサーバであるASP.NETを使用したASP.NETアプリケーションの「状態管理方式」に関する、下記の項目について説明する。

特に、「状態管理方式」の選択や「状態管理技術」の使い方を誤れば、性能の悪化や保守性の悪化、予期せぬセキュリティ問題が発生したり、拡張性・信頼性の要件が満たせないという問題などにも結びついたりするので注意が必要である。

Webアプリケーションの状態管理方式

サーバ ステートレスな状態管理方式

「サーバ ステートレスな状態管理方式」とはWeb・APサーバに状態を持たせない方式であり、必要なデータはDBサーバ上に永続化するか、クライアント・サーバ間でHTTPのリクエスト ⇒ レスポンス ⇒ リクエストと状態を持ち廻る方式である。この場合、サーバはリクエストを処理してレスポンスを返した段階でWeb・APサーバ上のメモリの情報を破棄し、Web・APサーバ上に状態を保持しない。

サーバ ステートレスな状態管理方式

表:サーバ ステートレスな状態管理方式の処理概要

順番処理の実装箇所処理
クライアント / サーバモジュール
クライアント側wwwブラウザ「サーバ処理1」に対して「ページ1」を要求する。
サーバ側サーバ処理1「ページ1」のHTMLをクライアントに出力する。
クライアント側wwwブラウザ
ページ1
「Form」や「クエリー ストリング」に処理を継続するために必要な情報を含め「サーバ処理2」を要求する。
サーバ側サーバ処理2,3「サーバ処理2」 ⇒ 「サーバ処理3」と情報を持ち廻る時は、「Form」・「HTTP Context」などに情報を格納した後にサーバ処理を遷移し、「ページ2」のHTMLをクライアントに出力する。

サーバ ステートフルな状態管理方式

「サーバ ステートフルな状態管理方式」とはWeb・APサーバに状態を持たせる方式であり、必要なデータをWeb・APサーバ上のメモリ領域に保持する。

サーバ ステートフルな状態管理方式

この方式では、Web・APサーバ上のメモリ領域に状態を保持する(主にSessionが使用される)。このため、保持すべきデータをDBサーバ上に永続化したり、クライアント・サーバ間で状態を持ち廻ったりしなくても、画面間で情報を引き継ぐことができる。また、「サーバ ステートレスな状態管理方式」で使用した技術も併用できる。

ASP.NETにおける状態管理技術

以下の表に、

表:ASP.NETにおける状態管理技術の説明

項番状態管理技術説明
FormデータHTTPのメッセージ ボディを使用する。送信時はFormのポストで送信する。受信時はHTMLとして受信する。
ViewState?Hiddenを仕様した状態保持の仕組みだが、ASP.NETの独自の基盤機能が付加されている。
Query stringHTTPのリクエストのメッセージ ヘッダーを使用する。
CookieHTTPのメッセージ ヘッダーを使用する。
Server.Transfer+HTTP Context領域Server.Transfer処理はサーバ処理を遷移するためのメソッド、HTTP Context領域はリクエスト単位で確保する領域である。
ASP.NET独自の呼称だが、類似した技術が、似たような仕組みは各APサーバにも用意されている。
SessionASP.NETの組込みオブジェクト。Webアプリケーションで一般的に使用されるが、ASP.NETの独自の基盤機能が付加されている。
ApplicationASP.NETの組込みオブジェクト。アプリケーション単位の共通情報を管理する。
静的変数ASP.NETプログラムのグローバル変数。
CacheASP.NETの組込みオブジェクト。キャッシュ処理用に使用される。

表:ASP.NETにおける状態管理技術の特徴

項番状態管理技術区分
ASP.NET独自Webアプリケーション一般ステートレスステートフル
Formデータ
ViewState?
Query string
Cookie
Server.Transfer+HTTP Context領域
Session
Application
静的変数
Cache

ASP.NETの特徴

ASP.NETが、今までのWeb開発技術から大きく進化した点に、VB6.0以前のバージョンや.NETのWindowsアプリケーションなどで知られている「イベント ドリブンのプログラミング モデル」が採用された点が挙げられる。この「イベント ドリブンのプログラミング モデル」を可能にしたことで、ASP.NETでは、「同一の画面に対してポストバックする方式」が標準となった。

ポストバックとは

「同一の画面に対してポストバックする方式」とは、自身を生成した画面(aspx)に対してForm情報をポストする方式のことであり、ASP.NETのアプリケーションは通常、以下のように動作する。

ASP.NETのポストバック

ASP.NETでは、画面上でボタンを押すと自分の画面に対して「Form情報」が「ポストバック」される。サーバ側では、画面上のどのボタンが押されたのかを「Form情報」から自動的に解析し、画面に登録されているイベント ハンドラに自動的に処理を振り分ける。このように、従来の技術と比べASP.NETでは「動的ページ」と「サーバ処理」の関係が、「画面」という単位でわかりやすく対応付くようになった。また、従来の技術では同一画面を再表示する場合、ポストされた「Form情報」をサーバ側で再取得して、再びHTMLの各要素のvalueに設定して出力する必要があったが、ASP.NETのWebコントロール(以下、Webコントロールと略す)では、Webコントロールの情報をサーバ側で復元する処理も自動化されている。

ViewState?とは

ASP.NET独自のサーバ ステートレスな状態管理技術として「ViewState?」がある。本節では、この「ViewState?」がどの様な技術で実装され、どの様な目的で使用されているかについて説明する。

という実装になっている。

ハッシュ値の付与や、base64エンコードを除けば 、オブジェクトのデータをシリアライズ・デシリアライズし、Hiddenタグを使用して文字列形式で情報を保持しているだけである。このため、「ViewState?」はサーバ ステートレスな状態管理技術に分類できる(設定によっては暗号化も可能であるが、デフォルトの設定では暗号化されないので注意が必要である)。

次項では、「ViewState?」の利用目的の詳細について説明する。

ViewState?を使用したアプリケーション基盤処理

ViewState?」には、イベント ドリブンのプログラミング モデルを実現するための使用方法が存在する。この用途では、利用者から意図することなく利用される。この用途とは、Webコントロールに関する表示状態の情報をViewState?に保存することで「ポストバック」の際に、

といった用途である。

ViewStateを使用したアプリケーション基盤処理

ViewState?を使用したサーバ ステートレスな状態管理

前項に示した「ViewState?」の使用方法以外には、同一画面内でのみ機能する(画面間を跨った利用は不可能)、サーバ ステートレスな状態管理技術としての使用方法がある。この使用方法では、利用者が必要に応じてアプリケーションに実装する。この使用方法は、独自に「Hiddenタグ」を追加して、そこにシリアル化されたオブジェクト情報を保持する方式と大きな違いは無い。

Webフォームのメンバ変数は、Windowsフォーム内のメンバ変数のように情報を保持しない。また、サーバ ステートレスな状態管理方式を採用している場合、サーバ側のメモリも利用できない。このような場合に「ViewState?」を使用すれば、同一画面内でのみ状態を保持することができる。このため、見方によってはWebフォーム内の情報を保持する機構と解釈することもできる。

WindowsForms内のメンバ変数のように、Webフォーム内の情報を保持する機構

また、サーバ ステートフルな状態管理方式を採用している場合、Webフォーム内の情報を保持する処理を「Session」でも代替できるが、「ViewState?」の場合はデータ消去の手間がかからないというメリットがある。

ViewState?の使用上の注意点

アプリケーション基盤処理の注意点(事例)

ViewState?」を利用する際、最も注意しなければならない点は、「クライアント側にダウンロードされるHTMLデータが膨張し、ネットワーク トラフィックが増加して性能劣化に繋がる可能性がある」という点である。

繰り返すが、「ViewState?」は、イベント ドリブンのプログラミング モデルを可能にするASP.NETのアプリケーション基盤技術である。このため、意図的に利用していなくても、WebフォームがHTMLを出力する際に影ながら利用されてしまう。

このため、場合によっては無駄なHTMLデータが大量に出力されることになる。

例えば、読み取り専用のグリッド ビュー コントロールに表示データをデータ バインドし、クライアントに出力したとする。すると、ASP.NETの基盤処理により、自動的にデータ グリッド コントロールの表示状態の情報を「ViewState?」に出力してしまう。

ある事例では、1MBのHTMLテーブル データに対し1MBの「ViewState?」が出力され、必要な表示データが1MBなのに対し、実際にクライアント側にダウンロードされるHTMLデータが2倍の2MBに膨れ上がり、ネットワーク トラフィックが増加して性能劣化に繋がった。

不要な「ViewState」データによるデータの膨張とネットワーク・トラフィックの増加

この事例のグリッド ビュー コントロールは読み取り専用であったため、changeイベント ハンドラなどへの振り分けは必要なかった。

この事例での適切な対策としては、グリッド ビュー コントロールの「ViewState?」機能を無効に設定し、DB上のデータを再度取得するなどの方式が挙げられる。

ViewState?を使用してデータを保持する場合の注意点(事例)

ViewState?」を、Webフォーム内の情報を保持する機構として利用した場合も、大容量のデータを「ViewState?」に保持した場合は、クライアント側にダウンロードされるHTMLデータが膨張しネットワーク トラフィックが増加して性能劣化に繋がる。

ある事例では、ドロップ ダウン リスト コントロールなどにデータ バインドするマスタ データのDataSet?オブジェクトやDataTable?オブジェクトなどを「ViewState?」に保存して、HTMLデータが膨張しネットワーク トラフィックが増加して性能劣化に繋がった。

この事例での適切な対策としては、DB上のデータを再度取得したり、「Session」・「Cache」に格納した情報を利用したりする方式が挙げられる。

ViewState?の使用上の注意点まとめ

本項では、「ViewState?」の使用上の注意点をまとめる。

ViewState?」のデータ自体は、ただの「Hiddenデータ」として埋め込まれることを意識し、「ViewState?」を使用する際にはクライアント側にダウンロードされるHTMLデータが膨張し、ネットワーク トラフィックが増加して性能劣化に繋がることがないように注意を払う。

データを「ViewState?」に保持するより、DB上のデータを再度取得するか「Session」に格納した情報を利用する方が、処理効率は良い可能性がある。また、DB上のデータを再度取得するオーバーヘッドが問題となる場合で、データがマスタ データであれば、「Cache」を使用しても良い。

特に、ADO.NETのDataSet?オブジェクトやDataTable?オブジェクトなどをデータ バインド可能なWebコントロールが出力する「ViewState?」は、巨大になる傾向がある。以下にデータ バインド可能なWebコントロールを列挙しておく。

また、

などの処理がそもそも不要なWebコントロールに対しては、「ViewState?」の機能を停止し(Webコントロールの「ViewState?」の機能を停止させたい場合は、該当するWebコントロール「EnableViewState?」プロパティをfalseに設定する。)、クライアント側にダウンロードされるHTMLデータの膨張を抑止することも検討する。

状態管理技術の特徴

本章では、状態管理技術の特徴を解説する。

サーバ ステートレスな状態管理技術の共通的な特徴

以下、サーバ ステートレスな状態管理技術の共通的な特徴を簡単に説明する。

サーバ ステートフルな状態管理技術の共通的な特徴

以下、サーバ ステートフルな状態管理技術の共通的な特徴を簡単に説明する。

個別の「状態管理技術」の特徴

本節では、個別の「状態管理技術」の特徴を解説する。

Session

サーバ ステートフルな状態管理技術なので、4.2節に示した特徴を持つ。クライアントのブラウザがWebサーバに接続したタイミングで、サーバがクライアントに返す「SessionID(基本的にCookieを利用)」を利用することにより、それ以降の接続でユーザのセッションを識別できるようになり、Webサーバ上のメモリ上にユーザ毎の「Session」を使用できる。仕組みは上記に示した簡単なものであるが、利用する際は、更に以下の点を考慮すると良い。

Application、静的変数

サーバ ステートフルな状態管理技術なので、4.2節に示した特徴を持つ。

Cache

サーバ ステートフルな状態管理技術なので、4.2節に示した特徴を持ち、更に「Application」にキャッシングに必要なアプリケーション基盤機能を実装したような特徴を持っている。

ViewState?

サーバ ステートレスな状態管理技術なので、4.1節に示した特徴を持つ。また、多くは3.2節、3.3節で説明済みである。

Cookie

サーバ ステートレスな状態管理技術なので、4.1節に示した特徴を持ち、また、主に固定データの持ち廻りに使用される(更新用のAPIも用意されているため、可変データの持ち廻りも可能である)。

このため、アプリケーション基盤技術である、

などの情報を持ち廻る用途にも利用されている。

それ以外に、パーソナライズ状態の維持(ログインされていない状態でも、ユーザを識別した状態で画面を表示するなどの機能のこと。これによりサイトの利便性を向上させることができる)という用途にも使用される。

負荷分散(冗長化)構成と状態管理方式

拡張性・信頼性を確保するために、負荷分散(冗長化)構成をとるケースがある 。

Windows Serverの拡張性・信頼性を確保するための、負荷分散(冗長化)構成例

クライアント リクエストは、NLB (あるいは負荷分散ハードウェア、DNSラウンドロビン)を用いて各ノード(Webサーバ)に分散される。

この場合、クライアント リクエストを別のノードへ振り替えられるようにするため 、各ノードは通常サーバ ステートレスである。特定のノードに障害が発生した場合やメンテナンスのためにサービスを中断する必要がある場合、クライアント リクエストは自動的に別のノードへと振り替えられる。

バックエンド データ層は、MSCS 上にホストする。障害が発生した場合やメンテナンスのためにサービスを中断する必要がある場合、正常なノードがデータへのアクセスを提供し続ける。

ネットワーク負荷分散(冗長化)構成をとる場合、「状態管理技術」である、Session、ViewState?、Cookie(Forms認証(暗号化されたCookie認証チケットを使用するカスタム認証の実装を支援するASP.NETの基盤機能))を正しく利用するに当たって、サーバの構築・設定に特別な配慮が必要になる。

本章では、このサーバの構築・設定のポイントについて説明する。

負荷分散(冗長化)構成とSession

デフォルトの「Session」の設定では、asp.netのホストプロセスの使用する仮想メモリにデータを格納する。このため、ネットワーク負荷分散(冗長化)構成を組み「Session」などの、各ノードのインプロセスのメモリ領域を使用する場合 、同一クライアントからの要求は、特定のノードへ割り当てる必要がある。

これは、クライアント リクエストがノードを跨いだ場合、各ノードの同期のとれていないSessionを使用してしまうためである。このため、同一クライアントからの要求は、特定のノードへ割り当てる必要がある。NLBクラスタの場合、Affinityパラメタを「単一モード」に設定することで、同じクライアント(IPアドレス)から発信された全てのTCP接続を、クラスタ内の特定の「物理サーバ」に送ることができる。

Windows ネットワーク負荷分散した場合のSession

ステート サービス・ステート データベースの導入

5.1節に示した問題を回避するために、ASP.NETでは「Session」の永続化の専用システム(ステート サービス・ステート データベースと呼ばれる)を使用して、プログラムから意識することなくネットワーク負荷分散(冗長化)の構成ノード共通の「Session」に状態を永続化するインフラの構築が可能である。

ステート サービス・ステート データベースの特徴については以下の表にまとめる。

表ステート サービス・ステート データベースの特徴

項番状態管理技術説明
ステート サービスWindowsサービスのプロセス上に「Session」のデータを格納する方式である。一般的には、専用サーバにステート サービスを持たせる。
ステート データベースSQL Serverのストレージ上に「Session」のデータを格納する方式である。この場合、専用サーバにステート データベースを持たせる。

ステート サービス・ステート データベースを導入した場合、どのノードからも「クライアントa」に対する「Session-a」が取得可能になる。この構成では、同一クライアントからの要求を、同一のWebサーバへ割り当てる必要はない。このため、ラウンドロビンなど、動的な振り分けにも対応可能になる。

ステート サービス・ステート データベースを導入した場合のSession

ステート サービス・ステート データベースの導入と、信頼性の関係

ステート サービス・ステート データベースを利用すると、ネットワーク負荷分散(冗長化)構成を組み「Session」を使用する場合も、同一クライアントからの要求を、特定のノードへ割り当てる必要がなくなる。

また、あるノードで障害が発生して、ネットワーク負荷分散(冗長化)の構成ノードから切り離されても、ユーザは、「Session」の情報を消失せずに、処理を続行できる。

これにより、Webアプリケーションの信頼性が向上する 。

障害発生時、負荷分散(冗長化)構成ノードを切り離す

ただし、ネットワーク負荷分散(冗長化)構成で、ステート サービス・ステート データベースを利用した場合、そこが「単一障害点」になる可能性があるので注意が必要になる。「単一障害点」を回避するための方法は、ステート データベースで使用するSQL ServerをMSCS、若しくはSQL Server 2005 SP1で実装されたデータベース ミラーリング機能でクラスタリングすることである。これにより、「単一障害点」がなくなる。

上記の施策で「単一障害点」を回避できるが、「単一障害点」を回避して信頼性を向上させるだけのために、ステート データベースで使用するSQL ServerのMSCS構成を新規導入するのは、技術的・予算的に難しい場合が多い。

このような場合は、下記の折衷案を検討するべきである。

補足:障害発生時の「Session」の引継ぎはMSCS構成でも不可能であるため、「Session」を他ノードに引き継ぐ場合はMSCS構成ではなく、必ずネットワーク負荷分散(冗長化)構成と、ステート サービス・ステート データベースを構成する必要がある。これは、MSCSがサーバのメモリ状態をフェイル オーバーする機能を備えていない為である。MSCSでは、共有ディスク上の状態データのみ引き継ぐことができる。

負荷分散(冗長化)構成とデータの暗号化・検証

ステート サービス・ステート データベースに保存される「Session」データ、Hiddenタグに出力される「ViewState?」データ、Forms認証の基盤機能を使用した場合に発行される「Cookie認証チケット」は、各ノードの.NETの設定にあるmachineKey要素の情報で暗号化・検証される 。

このため、ネットワーク負荷分散(冗長化)構成を組み、以下の条件に当該する場合は、machineKey要素をネットワーク負荷分散(冗長化)の構成ノード全体で統一しておく必要がある。

machineKey要素をネットワーク負荷分散(冗長化)の構成ノード全体で統一することにより、クライアントのリクエストが別のノードに振り分けられた場合でも、暗号化された「Session」・「ViewState?」・「Cookie認証チケット」を復号化・検証できるようになり、処理を続行できる。

machineKey要素を負荷分散の構成ノード全体で統一

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS