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

戻る
戻る
 
次へ
次へ
 

19 クラスタ・アプリケーションのセッション管理

クラスタ・アプリケーションには、信頼性のある高性能なHTTPセッション管理が必要です。残念なことに、クラスタ環境へ移行すると、セッション管理に関する課題がいくつか発生します。ここではこれらの課題について説明し、解決策と推奨される対処方法を提案します。また、Oracle Coherence*Webに組み込まれているセッション管理機能について説明します。

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

基本的な用語

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

Coherenceは、クラスタ・アプリケーションに対してリアルタイムの、完全に一貫したデータ共有を行うことのできるデータ管理製品です。Coherence*Webは、Coherenceに組み込まれているセッション管理モジュールです。HTTPセッション・モデル(セッション・モデル)は、Coherence*Webでのセッション状態の物理的な表現方法を説明します。Coherence*Webには3つのセッション・モデルがあります。モノリシック・モデルでは、すべてのセッション状態を単一のエンティティとして保存し、すべての属性を単一の操作としてシリアライズおよびデシリアライズします。トラディショナル・セッションモデルでは、すべてのセッション状態を単一のエンティティとして保存しますが、属性のシリアライズおよびデシリアライズは個別に行います。スプリット・モデルはトラディショナル・モデルを拡張するものですが、大きいセッション属性は個々の物理エンティティに分割されます。これらのモデルのアプリケーションについては後述します。

"モノリシック、トラディショナル、スプリットの各セッション・モデルの詳細は、Coherence FAQの適切なセッション・モデルの選択に関する項を参照してください。特定のモデルを使用するようCoherenceを構成する方法についても説明されています。

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

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

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

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

セッション属性を複数のJVMにまたがって処理する場合、そのセッション属性はシリアライズする必要があります。これはクラスタ化の要件です。セッション属性の一部のフィールドを、一時フィールドと宣言することによって非クラスタ化することができます。これにより、セッション属性のすべてのフィールドをシリアライズ可能にする必要はなくなりますが、該当する属性はバックアップ・サーバーに完全には複製されません。この方法を使用する開発者は、これらの属性フィールドが失われてもアプリケーションが一貫して動作可能なことを慎重に確認する必要があります。多くの場合、この方法を使用すると、単純にすべてのセッション属性をシリアライズ可能なオブジェクトに変換するよりも難しくなります。ただし、1つのセッションでキャッシュされるユーザー固有データが大量にある場合には、便利なこともあります。

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アプリケーション間のデータ共有

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

信頼性と可用性

アプリケーションは、ユーザーのセッション状態を適切に維持し、そのユーザーにとって正しい動作を示すことを保証する必要があります。アプリケーションの設計レベルで可用性に関する考慮事項がいくつか発生しますが、これはクラスタ・アプリケーションおよび非クラスタ・アプリケーションの両方に該当します。たとえば、アプリケーションでは、ユーザーの処理が冪等であること(つまり、ユーザーが1つのHTMLフォームを誤って2回送信する場合の処理が可能であること)を確認する必要があります。

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

同時リクエストが存在する可能性がある場合、Coherence*Webでは、単一のサーバーが排他的にアクセスするようにセッションをロックすることにより、セッション状態の同時変更を管理します(複数のサーバーにまたがる場合も同様)。Coherence*Webを使用すると、開発者は、セッション・アクセスを1回につき1つのサーバーに制限するか(デフォルト)、1回につき1つのスレッドに制限するかを指定できます。

一般的に、セッション属性はすべて、可能であれば不変オブジェクトとして処理する必要があります。そうすることで、開発者は属性を変更するときに意識して気付くことができます。可変オブジェクトの場合、属性を変更するには通常2つの手順が必要です。属性オブジェクトの状態を変更してから、javax.servlet.http.HttpSession.setAttribute()を呼び出すことにより、変更済の属性オブジェクトを使用してセッションを手動で更新します。つまり、属性値が変更された場合、アプリケーションでは常にsetAttribute()を呼び出す必要があるということです。そうしないと、変更済の属性値はバックアップ・サーバーにレプリケートされません。Coherence*Webでは、セッションから取得したすべての可変属性を追跡するため、setAttribute()が呼び出されていない場合でも、これらの属性は自動的に更新されます。このことは、クラスタ化用に設計されていないアプリケーションをクラスタ環境で実行する場合に役立ちます。

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

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

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

最後に知っておくべき問題は、負荷が大きい場合、ネットワークの混雑によってサーバーのセッション属性変更内容が失われる場合があることです。ログには失われた属性に関する情報が含まれますが、これが高可用性の計画で最も重要な局面を示します。必ず、最大の負荷ですべてのアプリケーション・コンポーネントをテストして、フェイルオーバーとフェイルバックが期待どおりに行われることを確認してください。多くのアプリケーションでは、99%の負荷であってもまったく問題が見られませんが、アプリケーションの可用性の本当のテストは、システムが完全に飽和状態のときに発生します。

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

クラスタ環境に移行する場合は、セッションのサイズを考慮することが重要です。メモリー使用量は、アプリケーションがクラスタ化されているかどうかにかかわらず重要ですが、クラスタ・アプリケーションでは、大規模なセッションで増加するCPUやネットワークの負荷も考慮する必要があります。インメモリー・セッションを使用する非クラスタ・アプリケーションではセッション状態をシリアライズおよびデシリアライズする必要はありませんが、クラスタ・アプリケーションでは、セッション状態が更新されるたびに、この処理を行う必要があります。セッション状態をシリアライズしてネットワーク経由で転送することは、アプリケーションのパフォーマンスにおいて重要な要素になります。このような理由から、サーバーでは通常、セッションのサイズを数KB以下に制限する必要があります。

Coherence*Webのトラディショナルおよびモノリシックの各セッション・モデルには同じ制限要素がありますが、スプリット・セッション・モデルは大規模なHTTPセッションを効率的にサポートするように明示的に設計されています。単一のクラスタ化されたキャッシュ・エントリを使用して小さいセッション属性をすべて含めると、セッションまたはセッションの比較的小さい属性に対してアクセスおよび更新を行う際のネットワーク通信量が最小になります。各属性を個々にデシリアライズすると、CPU使用量が最小になります。比較的大きいセッション属性を別々のクラスタ化されたキャッシュ・エントリに分割することにより、Coherence*Webでは、アプリケーションに費用がかかるのは、該当する属性が実際にアクセスまたは更新されたときのみになります。また、Coherence*WebではCoherenceのデータ管理機能を利用しているため、ニア・キャッシュ、NIOバッファ・キャッシュおよびディスクベース・オーバーフローなど、基礎となる機能をすべてセッション属性の管理に使用できます。

図19-3は、パフォーマンスをセッション・サイズの関数として示しています。各セッションは、10文字の文字列10個と、10,000文字の文字列0〜4個で構成されています。各HTTPリクエストは、単一の小さい属性と単一の大きい属性(セッション内にある場合)を読み取り、リクエストの50%がこれらの属性を更新します。テストは2つのサーバーで構成されるクラスタで行われました。トラディショナル・モデルとモノリシック・モデルではパフォーマンスが類似していることに注目してください。文字列のシリアライズとデシリアライズに使用されるCPUリソースが最小限であるため、実際に使用した属性のみをデシリアライズしても、パフォーマンスはほとんど向上しません。スプリット・モデルのパフォーマンス向上率は、セッション・サイズが1MB(大きい文字列100個)に達するまでに37:1を超えます。クラスタ環境では、必須データのみにアクセスするアプリケーション・リクエストのほうが、スケーラビリティおよびパフォーマンスが良くなる傾向が特に高いといえます。このことからも、セッションは適切なサイズに保つ必要があります。

図19-3 セッション・サイズの関数で示したパフォーマンス

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

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

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

スティッキーなロード・バランシングは、Coherence*Webのパフォーマンスを助長しますが、必須ではありません。Coherence*WebはCoherenceデータ管理プラットフォームをベースに構築されているため、セッション・データはすべてクラスタ全体でグローバルに参照可能です。Coherence*Webの通常のデプロイメントでは、セッション・データはニア・キャッシュ・トポロジに配置されます。ニア・キャッシュ・トポロジは、パーティション化されたキャッシュを使用して莫大な量のデータをスケーラブルかつフォルト・トレラントな方法で管理し、各アプリケーション・サーバーJVMのローカル・キャッシュと組み合せて、多く使用されるセッション状態に瞬時にアクセスできるようにします。スティッキーなロード・バランサは、Coherence*Webを使用する際に必須ではありませんが、使用すると主に2つのメリットがあります。ニア・キャッシュ・テクノロジを使用するため、ユーザー・リクエストが一貫して同じサーバーにルーティングされている場合は、セッション属性に対する読取りアクセスを瞬時に行うことができます。これは、ローカル・キャッシュを使用することにより、デシリアライズとセッション属性のネットワーク転送が不要になるためです。また、スティッキーなロード・バランシングを使用すると、Coherenceでは並行性をローカルで管理でき、ユーザー・リクエストが別のサーバーに再分配されたときにのみセッション・ロックを転送します。

結論

クラスタ化によって、アプリケーションのスケーラビリティと可用性を向上させることができます。Coherence*Webのようなクラスタ化ソリューションでは、開発者の多くの問題を解決できますが、開発者として成功するには、基礎となるテクノロジの限界と、その限界にどう対処するかを知っておく必要があります。プラットフォームの機能やユーザーの要求を理解することにより、開発者はユーザーとの距離を縮めることができます。