第15章 HTTP セッションステートレプリケーション

ソフトウェアロードバランサ

複数のコンピュータサーバー (クラスタ) に HTTP クライアントセッション要求を分散するよう設計された専用のソフトウェアベースのサービス。ソフトウェアロードバランサの主要な目的はリソース使用率を最大化し、要求応答時間を短縮し、サーバーの過負荷を防ぐことです。ロードバランサは、サーバーの負荷と可用性に基づいてクライアントセッション要求をサーバークラスタに転送します。

クライアントセッション

クライアント (アプリケーション) とサーバー間の半永久的な接続。ロードバランサは、永続化でクライアントセッションが作成されるかどうか、またはサーバーの負荷および可用性い基づいてクライアントセッションが再分散されるかどうかを決定します。

セッション永続化

単一のサーバーインスタンスにだけ割り当てられるクライアントセッション。ロードバランサはクライアントセッションに関連付けられたすべての HTTP 要求を割り当てられたサーバーインスタンスにだけルーティングします。セッションの永続化は、一般的にスティッキーセッションと呼ばれます。

スティッキーセッション

セッションの永続化を参照してください。

セッション内のクライアントが常に同じサーバーノードにルーティングされるようにロードバランサでセッションステート永続化を設定する方法については、「mod_jk のワーカーノードの設定」 を参照してください。
独自のセッション永続化は、サーバーで障害が発生した場合に、すべてのセッションステートデータが失われるため、最良のソリューションではありません。たとえば、顧客が Web サイトで買い物をするときにショッピングカートインスタンスをホストしているサーバーで障害が発生した場合、ショッピングカートに関連付けられたセッションステートデータは永久的に失われます。
クライアントセッションデータの損失を回避する方法の 1 つは、クライアント内のサーバーでセッションデータをレプリケートすることです。サーバーノードで障害が発生した場合やサーバーノードがショットダウンされた場合、ロードバランサは任意のサーバーノードに次のクライアント要求をフェールオーバーし、同じセッションステートを取得できます。
Web アプリケーションでセッションレプリケーションを設定せずに、セッション永続化をサポートするロードバランサを使用すると、セッションステートレプリケーションのコストを回避することにより実装のスケーラビリティが実現されます。セッションの各要求は常に同じノードで処理されます。
セッションステートレプリケーションは、基本的なセッション永続化よりもコストが高くなりますが、セッションステートデータに提供される安定性は、負荷分散されたクラスタを作成する場合に重要になります。

15.1. アプリケーションでのセッションレプリケーションの有効化

Web アプリケーションのレプリケーションを有効にするには、web.xml 記述子でアプリケーションを分散可能としてタグ付けする必要があります。以下に例を示します。
<?xml version="1.0"?> 
<web-app  xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
                              http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
          version="2.4">
          
    <distributable/>
    
</web-app>
また、jboss-web.xml ファイルで replication-config 要素を使用することにより、セッションレプリケーションを使用できます。ただし、replication-config 要素は、以下で説明された 1 つ以上のデフォルト値を使用できる場合にのみ設定する必要があります。例は以下のとおりです。
<!DOCTYPE jboss-web PUBLIC
    "-//JBoss//DTD Web Application 5.0//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">

<jboss-web>
   
   <replication-config>
      <cache-name>custom-session-cache</cache-name>
      <replication-trigger>SET</replication-trigger>
      <replication-granularity>ATTRIBUTE</replication-granularity>
      <replication-field-batch-mode>true</replication-field-batch-mode>
      <use-jk>false</use-jk>
      <max-unreplicated-interval>30</max-unreplicated-interval>
      <snapshot-mode>INSTANT</snapshot-mode>
      <snapshot-interval>1000</snapshot-interval>
      <session-notification-policy>com.example.CustomSessionNotificationPolicy</session-notification-policy>
   </replication-config>

</jboss-web>
すべての設定要素はオプションであり、デフォルト値が使用可能な場合は省略できます。この組み合わせは一般的に使用され、残りの値はデフォルト値からほとんど変更されません。一般的に使用される値について最初に説明します。
<replication-trigger> 要素は、セッションデータをクラスタでレプリケートすることをコンテナがいつ考慮するかを決定します。この設定の理由は、セッション属性として保存された変更可能なオブジェクトがセッションからアクセスされた後に、setAttribute 呼び出しが存在しない場合、オブジェクト (したがって、セッションステートも) が変更され、レプリケートする必要があるかどうかをコンテナが明確に認識できないことです。この要素は 3 つの有効な値を持ちます。
  • SET_AND_GET は保守的であり、最適ではありません (パフォーマンスの点で)。内容が変更されず、単にアクセスされた場合であってもセッションデータは常にレプリケートされます。この設定は JBoss Enterprise Application Platform 4 では (ある程度は) 適切です。なぜなら、この設定を使用すると、要求ごとに、セッションのタイムスタンプのレプリケーションがトリガされるためです。max_unreplicated_interval を 0 に設定すると、同じことを非常に小さいコストで実現できるため、Enterprise Application Platform 5 で SET_AND_GET を使用することは適切ではありません。
  • SET_AND_NON_PRIMITIVE_GET は保守的であり、非プリミティブタイプがアクセスされた場合にのみレプリケートされます (つまり、このオブジェクトは IntegerLongString などのよく知られた不変な JDK タイプではありません)。これはデフォルト値です。
  • SET を使用する場合は、データをレプリケートする必要があるときに開発者がセッションで setAttribute を明示的に呼び出すことが前提とされます。この設定では、不必要なレプリケーションが回避され、パフォーマンスが大幅に向上しますが、セッションで保存された変更可能なオブジェクトが変更されたときに常に setAttribute が呼び出されるようにするために非常に優れたコーディングが必要になります。
すべてのケースで、setAttribute を呼び出すと、セッションがレプリケーションを必要としているとマークされます。
<replication-granularity> 要素は、セッションレプリケーションが必要なことをコンテナが決定する場合に、レプリケート対象の粒度を決定します。サポートされる値は以下のとおりです。
SESSION
属性が変更されたと見なされた場合に全体のセッション属性マップをレプリケートすることを指定します。レプリケーションは要求側で行われます。このオプションにより、ほとんどのデータがレプリケートされ、レプリケーションコストが最大になります。ただし、すべての属性値は常に一緒にレプリケートされるため、セッションがシリアル化解除されたときに属性値間の参照は破壊されなくなります。このため、これはデフォルト設定になります。
ATTRIBUTE
セッションが変更可能と見なす属性のみがレプリケートされることを指定します。レプリケーションは要求側で行われます。大量のデータを扱うセッション (一部のデータが頻繁に更新されない) では、このオプションによりレプリケーションパフォーマンスが大幅に向上することがあります。ただし、これは、お互いに参照を共有する異なる属性のオブジェクトを格納するアプリケーションには適していません (たとえば、Address オブジェクトへの参照を "wife" 属性の別の Person オブジェクトと共有する "husband" 属性の Person オブジェクト)。これは、属性が別々にレプリケートされ、セッションがリモートノードでシリアル化解除された場合は、共有された参照が破壊されるからです。
replication-config 要素下の他の要素はほとんど使用されません。
<cacheName>
分散可能なセッションを格納し、クラスタでレプリケートするために使用する必要がある JBoss Cache 設定の名前を指定します。この要素を使用すると、さまざまなキャッシュ特性が必要な Web アプリケーションで、個別の別々に設定された JBoss Cache インスタンスの使用を指定できます。JBoss Enterprise Application Platform 4 では、使用するキャッシュは Web アプリケーションごとに変更できず、サーバー全体の設定でした。デフォルト値は standard-session-cache です。Web 階層クラスタリングに関する JBoss Cache 設定の詳細については、「セッションステートレプリケーションに使用される JBoss Cache インスタンスの設定」 を参照してください。
<replication-field-batch-mode>
要求に関連付けられたすべてのレプリケーションメッセージを 1 つのメッセージにまとめるかどうかを指定します。これは、replication-granularityFIELD の場合にのみ適用できます。replication-field-batch-modetrue に設定されている場合は、セッション属性マップに格納されたオブジェクトに加えられた粒度の細かい変更が HTTP 要求が完了したときにレプリケートされます。それ以外の場合、これらの変更は発生したときにレプリケートされます。この値を false に設定することは推奨されません。デフォルト値は true です。
<useJK>
コンテナーで、この Web アプリケーションの負荷分散に JK ベースのソフトウェアロードバランサー (mod_jk、mod_proxy、mod_cluster など) を使用することを前提とするかどうかを指定します。true に設定されている場合は、コンテナーが各要求に関連付けられたセッション ID を調べ、フェールオーバーを検出した場合にセッション ID の jvmRoute 部分を置き換えます。
これは、URL を JK ロードバランサで処理できない Web アプリケーションに対してのみ false に設定する必要があります。
<max-unreplicated-interval>
要求の最大間隔を秒単位で設定します。この時間後、要求によりセッションがダーティになったかどうかに関係なくセッションのタイムスタンプのレプリケーションが要求によりトリガされます。このようなレプリケーションにより、クラスタの他のノードはセッションのタイムスタンプの最新の値を認識し、フェールオーバー時にレプリケートされないセッションが間違って時間切れになることがなくなります。また、フェールオーバー後に、HttpSession.getLastAccessedTime() コールの値が適切になります。
デフォルト値は null (つまり、未指定) です。この場合、セッションマネージャーは組み込まれた JBoss Web Engine に関する jvmRoute 設定があるかどうかを確認して (「mod_jk と動作するよう JBoss を設定する」 を参照)、JK が使用されているかどうかを調べます。
値が 0 の場合は、セッションがアクセスされたときに必ずタイムスタンプがレプリケートされます。値が -1 の場合は、要求中の他のアクティビティ (属性の変更など) により、セッションに関連する他のレプリケーション作業が発生したときにだけタイムスタンプがレプリケートされます。HttpSession.getMaxInactiveInterval() 値よりも大きい正の値は設定ミスとして扱われ、0 に変換されます (つまり、各要求時にメタデータがレプリケートされます)。デフォルト値は 60 です。
<snapshot-mode>
セッションが他のノードにレプリケートされるタイミングを指定します。可能な値は INSTANT (デフォルト値) と INTERVAL です。
一般的な値 INSTANT は、レプリケーションを実行する要求処理スレッドを使用して要求終了時に変更を他のノードにレプリケートします。この場合、snapshot-interval プロパティは無視されます。
INTERVAL モードでは、snapshot-interval ミリ秒ごとに実行されるバックグラウンドタスクが作成され、変更されたセッションをチェックしてレプリケートします。
replication-granularityFIELD に設定されている場合、このプロパティは無効です。FIELD である場合は、instant モードが使用されます。
<snapshot-interval>
この Web アプリケーションに対して変更されたセッションをレプリケートするバックグラウンドタスクを開始する頻度 (ミリ秒単位) を定義します。snapshot-modeINTERVAL に設定されている場合のみ意味を持ちます。
<session-notification-policy>
登録された任意の HttpSessionListenerHttpSessionAttributeListener、または HttpSessionBindingListener にサーブレット仕様通知を送出するかどうかを管理するために使用する必要がある ClusteredSessionNotificationPolicy インターフェースの実装の完全修飾名を指定します。

重要

非クラスタ環境で適切なイベント通知がクラスタ環境で必ずしも適切であるとは限りません。通知が適切でない理由の例については、https://jira.jboss.org/jira/browse/JBAS-5778 を参照してください。適切な ClusteredSessionNotificationPolicy を設定すると、アプリケーション作成者は発行される通知を細かく制御できます。