ヘッダーをスキップ
Oracle® Coherenceスタート・ガイド
リリース3.7.1
B65028-01
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

19 クラスタ化されたアプリケーションのセッション管理

クラスタ化されたアプリケーションでは、信頼性とパフォーマンスに優れたHTTPセッション管理が必要になります。残念なことに、クラスタ環境に移行すると、セッション管理がいくつかの点で難しくなります。この記事では、これらの課題について説明するとともに、そのソリューションと推奨手法を提案します。Oracle Coherence*Webの組込みのセッション管理機能についても確認します。

Coherence*Webの使用の詳細は、『Oracle Coherence Oracle Coherence*Webユーザーズ・ガイド』を参照してください。

19.1 基本的な用語

HTTPセッション(セッション)とは、Webアプリケーション内でユーザーによる一連の相互作用が行われている期間を表します。セッションの状態とは、ユーザー固有の情報のコレクションです。このセッションの状態は一定期間維持されます。この期間は、通常、ユーザーの最初の相互作用で始まり、ユーザーの最後の相互作用のしばらく後(30分後など)に終了します。セッションの状態は、セッション属性の任意のコレクションで構成されます。各セッション属性はJavaオブジェクトであり、名前によって識別されます。スティッキー・ロード・バランシングとは、一連のサーバーにユーザー・リクエストを分散させる際、特定のユーザーからのリクエストが常に同じサーバーに送られるようにする処理を表します。

Coherenceは、クラスタ化されたアプリケーションで一貫性を完全に維持したリアルタイムのデータ共有を実現するデータ管理製品です。Coherence*Webは、Coherenceの一部として組み込まれているセッション管理モジュールです。HTTPセッション・モデル(セッション・モデル)は、Coherence*Webでセッションの状態を物理的にどのように表現するかを示します。Coherence*Webには、次の3つのセッション・モデルが含まれています。モノリシック・モデルでは、すべてのセッション状態が単一のエンティティとして保存され、すべての属性が単一の操作でシリアライズおよびデシリアライズされます。トラディショナル・モデルでは、すべてのセッション状態が単一のエンティティとして保存されますが、属性は個別にシリアライズおよびデシリアライズされます。トラディショナル・モデルの拡張であるスプリット・モデルでは、比較的大きなセッション属性が独立した物理エンティティに分離されます。

図19-1は、モノリシック、トラディショナルおよびスプリットの各セッション・モデルを示しています。

図19-1 Coherenceでサポートされているセッション・モデル

この図については前の文で説明しています。

19.2 クラスタ環境でのデータの共有

セッション属性を複数のJVM間で処理する場合は、属性をシリアライズ可能にする必要があります。これはクラスタ化では必須です。セッション属性の一部のフィールドを非クラスタ化することもできます。その場合、対象のフィールドを一時フィールドとして宣言します。それによって、セッション属性のすべてのフィールドをシリアライズ可能にする必要はなくなりますが、このような属性はバックアップ・サーバーに完全にレプリケートされません。アプリケーションの開発時にこのアプローチを採用する場合は、属性フィールドが失われても、アプリケーションで一貫性のある動作が可能なことを入念に確認する必要があります。一般に、このアプローチを採用すると、すべてのセッション属性をシリアライズ可能オブジェクトに単純に変換する場合よりも、作業が難しくなります。しかし、セッション内でユーザー固有のデータが大量にキャッシュされる場合は、このパターンが役立つことがあります。

J2EEサーブレットの仕様(バージョン2.2、2.3および2.4)では、サーブレットのコンテキストをクラスタ内で共有しないように規定しています。サーブレットのコンテキストをシングルトン・データ構造として使用している非クラスタ化アプリケーションでは、クラスタ環境への移行時に移植の問題が発生します。Coherence*Webではクラスタ化されたコンテキストのオプションをサポートしていますが、通常は、すべての開発チームが、J2EEの仕様に準拠したアプリケーション開発を目標とする必要があります。

クラスタ環境で発生する、より複雑な問題として、オブジェクトの共有の問題があります。クラスタ化されていないアプリケーションでは、2つのセッション属性が共通オブジェクトを参照している場合、その共通オブジェクトに対する変更は両方のセッション属性の一部として参照可能です。しかし、クラスタ化されたアプリケーションでは、多くの場合、これと異なります。ほとんどのセッション管理の実装では、計算リソースを無駄に使用しないために、必要に応じて個別にセッション属性のシリアライズとデシリアライズが実行されます。Coherence*Webは、(トラディショナルおよびスプリット・セッション・モデルにおいて)通常、この方法で動作します。共通オブジェクトを参照する2つのセッション属性を個別にデシリアライズする場合、共有されている共通オブジェクトは2回インスタンス化されます。共有されているオブジェクトの動作に依存する、容易に修正できないアプリケーション向けに、Coherence*Webは、セッション・オブジェクト全体を単一操作としてシリアライズおよびデシリアライズするモノリスティック・セッション・モデルのオプションを備えています。これによって、もともとクラスタ化を考慮して設計されていないアプリケーションに対する互換性が確保されます。

多くのプロジェクトが、複数のWebアプリケーション間でのセッション・データの共有を必要とします。この場合の課題は、通常、Webアプリケーションごとに固有のクラス・ローダーがあることです。それが原因で、Webアプリケーション間でのオブジェクトの共有が難しくなります。回避策として使用できる一般的な方法が2つありますが、それぞれ固有のトレードオフがあります。

図19-2は、クラスタ化(セッション状態のシリアライズ/デシリアライズ)によるWebアプリケーションまたはポートレット間のデータの共有を示しています。

図19-2 Webアプリケーション間のデータの共有

この図については前の文で説明しています。

19.3 信頼性と可用性

アプリケーションでは、ユーザーのセッション状態が適切に維持され、そのユーザーの動作が正しく表現されることを保証する必要があります。アプリケーションの設計レベルで、可用性に関するいくつかの考慮事項についてチェックします。これらの考慮事項はクラスタ化アプリケーションと非クラスタ化アプリケーションのどちらにも適用されます。たとえば、ユーザーのアクションは冪等である必要があります。HTMLフォームをユーザーが誤って2回送信した場合でも、アプリケーションで処理可能にする必要があります。

スティッキー・ロード・バランシングでは、通常、同時セッション更新に関連する問題が回避されます。これは、セッション状態のすべての更新が単一のサーバーによって実行されるためです(それにより、並行性管理が大幅に簡素化されます)。この場合、ユーザーが最初のリクエストを送信した後、そのリクエストが完全に処理される前に新しいリクエストを送信した場合でも、ユーザー・リクエストが重複しないというメリットがあります。HTMLフレームを使用すると、同時セッション更新は複雑になりますが、同じ一般パターンが適用されます。つまり、必ず1つの表示要素のみによって、セッション状態が更新されるようにします。

Coherence*Webでは、同時リクエストが発生する可能性がある場合、セッション状態の同時変更(複数のサーバーが関与する場合も含む)が管理されます。この場合Coherence*Webは、セッションをロックして単一サーバーによる排他的アクセスを可能にします。Coherence*Webによって、開発者は、セッションへのアクセスを一度に1つのサーバーに制限するか(デフォルト)、または一度に1つのスレッドに制限するかを指定できます。

原則的には、可能なかぎり、すべてのセッション属性を不変オブジェクトとして扱うようにします。それによって開発者は、属性を変更するときに、その変更を意識的に行うことができます。可変オブジェクトでの属性の変更は、多くの場合、2つのステップを必要とします。まず属性オブジェクトの状態を変更し、その後javax.servlet.http.HttpSession.setAttribute()をコールして、変更後の属性によってセッションを手動で更新します。属性値が変わった場合は常に、アプリケーションでsetAttribute()をコールする必要があります。コールしないと、変更後の属性値がバックアップ・サーバーにレプリケートされません。セッションから取得された可変属性はすべてCoherence*Webによって追跡されるため、setAttribute()をコールしていなくても、これらの属性が自動的に更新されます。これは、クラスタ化に対応するように設計されていないアプリケーションをクラスタ環境で動作させる場合に役立つことがあります。

セッションの状態は、通常、プライマリとバックアップの2つのサーバーで維持されます。スティッキー・ロード・バランサは、指定されたプライマリ・サーバーに各ユーザー・リクエストを送信し、セッション状態のあらゆるローカル変更をバックアップ・サーバーにコピーします。プライマリ・サーバーで障害が発生した場合、次のリクエストはバックアップ・サーバーに再ルーティングされるため、ユーザーのセッション状態は影響を受けません。これは非常に効率的なアプローチです(特に、サーバーでの障害の発生後に、クラスタで大量のレプリケーション・アクティビティが発生することがありません)。ただし、いくつかの欠点があります。セッションの状態はセッションの更新時にコピーされるため、セッションの更新後、次の更新までの間にプライマリ・サーバーとバックアップ・サーバーの両方で障害(または停止および再起動)が発生した場合、セッションの状態が失われます。この問題を回避するには、サーバー・インスタンスのクラスタの停止および再起動時に、各サーバーを30分待機させてから再起動します。30分の間隔によって、ユーザーが再びアクセスする確率が高くなります。再アクセスがあれば、セッションのレプリケーションをトリガーすることができます。また、この間隔をセッションのタイムアウト時間以上にすれば、ユーザーの再アクセスがなくても、セッションの状態は破棄されます。

Coherence*Webでは、再起動までのこの間隔は不要です。サーバーで障害や停止/再起動が発生すると、セッション・データが自動的に再配信されるためです。Coherenceが提供する位置の透過性によって、ノードで障害が発生してもデータの可視性に影響が及ぶことはありません。しかし、ノードの障害は冗長性には影響するため、最新のバックアップ・コピーを作成する必要があります。Coherence*Webのほとんどの構成では、クラスタの規模にかかわらず、2つのコンピュータ(プライマリとバックアップ)によって各セッション・データが管理されます。この構成の場合、1回のフェイルオーバー遷移をCoherenceで随時処理できます。サーバーで障害が発生した場合、現在のフェイルオーバー・プロセスの完了前に次のサーバー障害が発生しないかぎり、データが失われることはありません。最悪のシナリオは、小規模のクラスタの各サーバーに大量のセッション・データが格納されている場合です。この場合、リバランスに1、2分かかることがあります。クラスタのサイズを拡大するか、サーバーごとのデータの格納量を減らすと、フェイルオーバーのパフォーマンスが向上します。一般的なサーバーで構成される大規模なクラスタの場合、フェイルオーバー・プロセスは1秒もしないうちに完了することがあります。特に重要なアプリケーションについては、バックアップ・コンピュータの数を増やすことによって、Coherenceで管理できる同時障害数が多くなります。

クラスタ化されたアプリケーションでのシリアライズの必要性は、新たな障害発生の可能性をもたらします。1つのセッション属性のシリアライズで障害が発生すると、通常、残りのセッション属性がバックアップ・サーバーにコピーされなくなり、その結果、セッション全体が失われることがあります。Coherence*Webでは、この回避策として、シリアライズ可能オブジェクトのみをレプリケートし、シリアライズ不可オブジェクトについてはローカル・サーバー・インスタンスに維持します。

最後の注意点として、負荷が高い場合、ネットワークの輻輳が原因でセッション属性の変更がサーバーから失われることがあります。失われた属性についての情報はログに記録されます。ここから、高可用性計画の最も重要な側面がわかります。つまり、負荷を最大にしてすべてのアプリケーション・コンポーネントをテストし、フェイルオーバーとフェイルバックが期待どうりに動作することを確認する必要があるということです。多くのアプリケーションは99%の負荷でも問題ないように見受けられますが、アプリケーションの可用性が真に試されるのは、システムが飽和状態のときです。

19.4 スケーラビリティとパフォーマンス

クラスタ環境への移行時には、セッション・サイズが重要な考慮事項になります。メモリー使用量は、アプリケーションがクラスタ化されるかどうかにかかわらず影響要因となりますが、クラスタ化アプリケーションの場合はさらに、セッションが大規模な場合のCPU使用率とネットワーク負荷の増加についても考慮する必要があります。メモリー内セッションを使用する非クラスタ化アプリケーションではセッション状態のシリアライズ/デシリアライズは必要ありませんが、クラスタ化アプリケーションではセッション状態の更新時に毎回シリアライズ/デシリアライズを実行する必要があります。セッション状態のシリアライズと、その後のネットワークを介した転送は、アプリケーションのパフォーマンスに影響を及ぼす重要な要因になります。このような理由などから、サーバーでは、通常、セッション・サイズを2、3KB以下に制限する必要があります。

Coherence*Webのトラディショナル・セッション・モデルとモノリシック・セッション・モデルでは制限要因が共通していますが、スプリット・セッション・モデルは大規模なHTTPセッションを効率よくサポートするように明示的に設計されています。単一のクラスタ化されたキャッシュ・エントリを使用して小さいセッション属性のすべてを格納することによって、セッションまたはその比較的小さい属性に対するアクセスや更新時にネットワーク通信量が最小化されます。各属性を個別にデシリアライズすることによって、CPU使用率も最小化されます。Coherence*Webは、比較的大きいセッション属性を独立したクラスタ化キャッシュ・エントリに分離します。そのため、アプリケーションでそのような大きいセッション属性に関連するコストが発生するのは、対象の属性へのアクセスまたは属性の更新が実際に実行されたときのみに限定されます。また、Coherence*WebではCoherenceのデータ管理機能が活用されるため、ニア・キャッシング、NIOバッファ・キャッシング、ディスクベースのオーバーフローなど、基礎となるすべての機能をセッション属性管理に利用できます。

図19-3は、セッション・サイズに応じたパフォーマンスを示しています。各セッションは、10個の10文字の文字列と0 - 4個の10,000文字の文字列で構成されています。各HTTPリクエストでは、小さい属性1つと、大きい属性1つ(セッション内に大きい属性が存在する場合)が読み取られ、リクエストの50%でこれらの属性が更新されます。2つのサーバーから成るクラスタで、テストが実行されました。トラディショナル・モデルとモノリシック・モデルのパフォーマンスはだいたい同じである点に注目してください。文字列のシリアライズ/デシリアライズでは最小限のCPUリソースしか消費されないため、実際に使用された属性のみのデシリアライズによるパフォーマンスの向上はほとんどありません。スプリット・モデルによるパフォーマンスの向上率は、セッション・サイズが1MB(大きな文字列100個)に達するまでに37:1を超えます。特筆すべき点として、クラスタ環境では、基本的なデータにしかアクセスしないアプリケーション・リクエストについては、スケーラビリティとパフォーマンスの向上の可能性があります。これは、セッションを妥当なサイズに抑える必要がある理由の1つとなっています。

図19-3 セッション・サイズに応じたパフォーマンス

この図については前の文で説明しています。

もう1つの最適化方法は、セッション属性クラスでの一時データ・メンバーの使用です。Javaのシリアライズ・ルーチンは、一時フィールドを無視するため、セッション属性がクラスタ化されているか、単一のクラスタ・メンバーに分離されているかを制御するための非常に便利な手段になります。これは、データが他のデータソースから遅延ロードされる(したがって、サーバーのフェイルオーバー・プロセスでは再計算される)場合や、絶対的な信頼性を必要としないシナリオで役立ちます。セッション状態の一部が失われてもアプリケーションに支障がなく、ユーザーへの影響がまったくない(または許容範囲内)である場合は、パフォーマンス上のメリットを考慮する価値がある場合があります。同様に、スケールの大きいアプリケーションでは、セッションの喪失をセッションのタイムアウトとして処理し、ユーザーにアプリケーションへの再ログインを要求することもめずらしくありません(これには、アプリケーション・セッションの状態に関するユーザーの期待を適切に設定するという暗黙的なメリットがあります)。

スティッキー・ロード・バランシングは重要な役割を果たします。なぜなら、セッションの状態はクラスタ全体でグローバルに参照可能なわけではないためです。スケールの大きいクラスタでは、ユーザー・リクエストは、通常、一連のステートレス・ロード・バランサを介してアプリケーション層に入り、これらのバランサによって、Microsoft IISやApache HTTP Serverなどの一連のスティッキー・ロード・バランサに(ある程度ランダムに)再分配されます。これらのスティッキー・ロード・バランサは、リクエストのHTTPヘッダーを解析して、そのリクエストを処理しているサーバー・インスタンスを(セッションCookieに指定されたサーバーIDに基づいて)判別するという、より集中的な計算を必要とする処理を行います。なんらかの理由でリクエストが誤ってルーティングされた場合、セッションの整合性が失われます。たとえば、一部のロード・バランサでは、大量(64KB超など)のPOSTデータを含むリクエストのHTTPヘッダーが解析されず、このようなリクエストが適切なサーバー・インスタンスにルーティングされないことがあります。ルーティング障害のその他の原因として、セッションCookie内のサーバーIDの破損や形式の誤りなどがあります。これらの問題のほとんどは、ロード・バランサを適切に選択するとともに、可能な場合はアプリケーションの設計で耐久力を組み込むこと(たとえば、大きなPOSTリクエストではいずれもセッション状態に対するアクセスや変更を行わないなど)によって対処できます。

スティッキー・ロード・バランシングはCoherence*Webのパフォーマンスを促進しますが、必須ではありません。Coherence*WebはCoherenceデータ管理プラットフォームを基盤としているため、すべてのセッション・データがクラスタ全体でグローバルに参照可能です。Coherence*Webの標準的なデプロイメントでは、セッション・データがニア・キャッシュ・トポロジに配置されます。このトポロジでは、パーティション化されたキャッシュの使用により、膨大なデータがスケーラビリティとフォルト・トレランスのある方法で管理されるとともに、各アプリケーション・サーバーJVMのローカル・キャッシュによって、よく使用されるセッション状態へのアクセスが迅速化されます。スティッキー・ロード・バランサはCoherence*Web使用時に必須というわけではありませんが、このバランサの使用によって2つの重要なメリットが得られます。ニア・キャッシュ・テクノロジが使用されるため、ユーザー・リクエストが常に同じサーバーにルーティングされるのであれば、セッション属性への読取りアクセスが迅速化されます。なぜなら、ローカル・キャッシュを使用することで、コストのかかるセッション属性のデシリアライズとネットワーク転送が不要になるためです。また、スティッキー・ロード・バランシングによって、Coherenceで並行性をローカルで管理できるようになります。ユーザー・リクエストが別のサーバーにリバランスされるときにのみ、セッション・ロックが転送されます。

19.5 結論

クラスタ化によって、アプリケーションのスケーラビリティと可用性を高めることができます。Coherence*Webなどのクラスタ化ソリューションは開発者の多くの問題を解決しますが、開発を成功させるためには、基礎となるテクノロジの制限とその対処方法を認識する必要があります。開発者は、プラットフォームが提供する機能とユーザーの要求内容を把握することによって、これら2つの間のギャップを埋めることができます。