スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

TomcatのセッションIDのクッキー名の変更

以下の2つのプロパティで変更できる。

org.apache.catalina.SESSION_COOKIE_NAME - クッキー名
org.apache.catalina.SESSION_PARAMETER_NAME - URL書き換えのパラメータ名

以下は、Tomcat起動時に呼ばれる「catalina.sh」で設定した例(80行目くらいに記述)。

-----
JAVA_OPTS=-Dorg.apache.catalina.SESSION_COOKIE_NAME=JSESSIONID2
-----
スポンサーサイト

HttpSessionをSessionIDから取得

そもそも標題のような要件が発生すること自体まれだと思うのだが、筆者が実際に陥った環境なのでまとめました。

■用意するもの
HttpSessionListener - セッションの作成/破棄をハンドリングするリスナ。
ServletContextListener - コンテキストの初期化をハンドリングするリスナ。

■ServletContextListenerの実装
contextInitialized()をオーバライドし、ハッシュマップをコンテキストスコープに保存。
保存した「activeUsers」をセッションIDでセッションを取得する為のオブジェクトとして使う。

-----
public class MyContestListener implements ServletContextListener {

@Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext context = event.getServletContext();

        HashMap activeUsers = new HashMap();
        context.setAttribute("activeUsers", activeUsers);
    }

-----

■HttpSessionListener
セッションの作成、破棄した時に呼ばれるメソッドをオーバライド。
セッションが作成されたらそれをセッションIDをキーにしてハッシュマップに保存。
セッションが破棄されたらセッションIDをキーにして削除。

-----
public class SessionListener implements HttpSessionListener{
    public void init(ServletConfig config){
    }

    public void sessionCreated(HttpSessionEvent event){
        HttpSession    session = event.getSession();
        ServletContext context = session.getServletContext();
        HashMap activeUsers = (HashMap)context.getAttribute("activeUsers");

        activeUsers.put(session.getId(), session);
        context.setAttribute("activeUsers", activeUsers);
    }

    public void sessionDestroyed(HttpSessionEvent event){
        HttpSession    session = event.getSession();
        ServletContext context = session.getServletContext();
        HashMap activeUsers = (HashMap)context.getAttribute("activeUsers");
        activeUsers.remove(session.getId());
    }

-----

■web.xmlに登録
filterの上に定義。

-----
    <listener>
        <listener-class>
          example.listener.MySessionListener
        </listener-class>
    </listener>

    <listener>
        <listener-class>
          example.listener.MyContestListener
        </listener-class>
    </listener>
-----

■セッションの取得
サーブレットでセッションIDからセッションを取得する処理。
今回は、Struts2で実装。ServletContextの取得方法が少しややこしい。

----
ActionContext ac = ActionContext.getContext();
ServletContext sc = (ServletContext)ac.get(StrutsStatics.SERVLET_CONTEXT);
HashMap sMap = (HashMap)sc.getAttribute("activeUsers");
HttpSession session2 = (HttpSession)sMap.get(session.getId());
-----

レプリケーション環境でも問題なく動きました。セッションを生成したタイミングでクラスタリングメンバの
HttpSessionListener#sessionCreated()が呼ばれていました。
セッションが二重持ちになってしまうのが気持ち悪いがセッションIDから取得する必要がある場合は、
このような実装で対応するのもありかも。

Tomcat6のCluster構築

今回は以下の環境でTomcatのクラスタリングを構成してみる。
同一マシン上にTomcatを2台立ててその間でSessionをレプリケーションします。

■環境
Windows XP
Apache Tomcat 6.0.32
Apache HTTP Server 2.2.17
└mod_proxy
└mod_proxy_balancer
└mod_proxy_ajp

■Tomcatの設定(2台)
1.インストール
server.xmlを起動オプションで指定して1台を仮想的に2台にする方法もあるようだが、
とりあえず今回は実体を2台配置する。
Tomcatは以下の場所にそれぞれインストール(以下、TOMCAT_HOME)

C:\srv\tomcat01\apache-tomcat-6.0.32
C:\srv\tomcat02\apache-tomcat-6.0.32

2.server.xmlの編集
ServerのポートとConnectのポート番号を2台で被らない様に変更する。
8080、8081は利用しないのでコメントアウトしてもよい。
(2台目のTomcatだけ変更)

2台目:
<Server port="8006" shutdown="SHUTDOWN">

<Connector port="8081" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8443" />

<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />

4.Apacheのロードバランシングの設定
mod_proxyとmod_proxy_balancerを使う。
とりあえず、sticksessionの設定はしない。

httpd.confの以下のLoadModuleのコメントアウトを解除。
一番最後の行にセクションを追加。
今回はWebアプリへ以下のURLでアクセスした場合に配下のTomcatへバランシングする設定。

URL:
http://localhost/session-rep-test/

-----
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

<IfModule mod_proxy_ajp.c>
<IfModule mod_proxy_balancer.c>
    <Location /session-rep-test/>
        ProxyPass balancer://session-rep-test/ nofailover=Off
    </Location>

    <Proxy balancer://session-rep-test/>
        BalancerMember ajp://192.168.1.11:8009/session-rep-test/ loadfactor=10
        BalancerMember ajp://192.168.1.11:8010/session-rep-test/ loadfactor=10
    </Proxy>
</IfModule>
</IfModule>
-----

■Tomcatのレプリケーション設定
各Tomcatのserver.xmlの要素の中に要素と要素を記述。
Tomcatのマニュアルでは要素をコメントアウトするだけで最小限の設定は済むと記述されていたが、
自分の試した環境では上手くレプリケーションされていなかった。
MembershipやRecieverは記載しなくても今回の環境では動作した。

<Engine name="Catalina" defaultHost="localhost">

    <!--For clustering, please take a look at documentation at:
            /docs/cluster-howto.html (simple how to)
            /docs/config/cluster.html (reference documentation) -->

    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">

    <Manager className="org.apache.catalina.ha.session.DeltaManager"
                             expireSessionsOnShutdown="false"
                             notifyListenersOnReplication="true"/>

    </Cluster>


■Webアプリのレプリケーション設定
web.xmlに以下の記述を追加。
今回は要素の直前に追記した。
これがないとレプリケーションの対象とならないらしい(未確認)

<distributable/>

■TomcatとApacheを起動
Tomcat2台→ApacheHTTPServerの順に起動。

以下は起動時のTomcatのログ

1台目:
-----
2011/02/13 0:55:29 org.apache.catalina.core.AprLifecycleListener init
情報: The APR based Apache Tomcat Native library which allows optimal performance~
2011/02/13 0:55:30 org.apache.coyote.http11.Http11Protocol init
情報: Coyote HTTP/1.1を http-8080 で初期化します
2011/02/13 0:55:30 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 2208 ms
2011/02/13 0:55:31 org.apache.catalina.core.StandardService start
情報: サービス Catalina を起動します
2011/02/13 0:55:31 org.apache.catalina.core.StandardEngine start
情報: Starting Servlet Engine: Apache Tomcat/6.0.32
2011/02/13 0:55:31 org.apache.catalina.ha.tcp.SimpleTcpCluster start
情報: Cluster is about to start
2011/02/13 0:55:31 org.apache.catalina.tribes.transport.ReceiverBase bind
情報: Receiver Server Socket bound to:/192.168.1.11:4000
2011/02/13 0:55:31 org.apache.catalina.tribes.membership.McastServiceImpl setupSocket
情報: Setting cluster mcast soTimeout to 500
2011/02/13 0:55:31 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
2011/02/13 0:55:32 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:4
2011/02/13 0:55:32 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
2011/02/13 0:55:33 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:8

情報: Webアプリケーションディレクトリ ROOT を配備します
2011/02/13 0:55:37 org.apache.catalina.ha.session.JvmRouteBinderValve start
情報: JvmRouteBinderValve started
情報: Server startup in 6396 ms
2011/02/13 0:56:02 org.apache.catalina.tribes.io.BufferPool getBufferPool
情報: Created a buffer pool with max size:104857600 bytes of type:org.apache.catalina.tribes.io.BufferPool15Impl
2011/02/13 0:56:03 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4001,{192, 168, 1, 11},4001, alive=1042,id={4 29 -40 -125 5 -14 72 26 -79 117 60 114 74 -77 21 111 }, payload={}, command={}, domain={}, ]
-----

2台目:
-----
2011/02/13 0:56:00 org.apache.catalina.core.AprLifecycleListener init
情報: The APR based Apache Tomcat Native library which allows optimal performance~
2011/02/13 0:56:02 org.apache.coyote.http11.Http11Protocol init
情報: Coyote HTTP/1.1を http-8081 で初期化します
2011/02/13 0:56:02 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 2279 ms
2011/02/13 0:56:02 org.apache.catalina.core.StandardService start
情報: サービス Catalina を起動します
2011/02/13 0:56:02 org.apache.catalina.core.StandardEngine start
情報: Starting Servlet Engine: Apache Tomcat/6.0.32
2011/02/13 0:56:02 org.apache.catalina.ha.tcp.SimpleTcpCluster start
情報: Cluster is about to start
2011/02/13 0:56:02 org.apache.catalina.tribes.transport.ReceiverBase bind
情報: Receiver Server Socket bound to:/192.168.1.11:4001
2011/02/13 0:56:02 org.apache.catalina.tribes.membership.McastServiceImpl setupSocket
情報: Setting cluster mcast soTimeout to 500
2011/02/13 0:56:02 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
2011/02/13 0:56:02 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000, alive=31386,id={8
0 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={}, domain={}, ]
2011/02/13 0:56:03 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:4
2011/02/13 0:56:03 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
2011/02/13 0:56:03 org.apache.catalina.tribes.io.BufferPool getBufferPool
情報: Created a buffer pool with max size:104857600 bytes of type:org.apache.catalina.tribes.io.BufferPool15Impl
2011/02/13 0:56:04 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:8

情報: Starting clustering manager at /session-rep-test
2011/02/13 0:56:05 org.apache.catalina.ha.session.DeltaManager getAllClusterSessions
警告: Manager [localhost#/session-rep-test], requesting session state from org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:40
00,{192, 168, 1, 11},4000, alive=34520,id={80 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={}, domain={}, ]. This op
eration will timeout if no session state has been received within 60 seconds.
2011/02/13 0:56:06 org.apache.catalina.ha.session.DeltaManager waitForSendAllSessions
情報: Manager [localhost#/session-rep-test]; session state send at 11/02/13 0:56 received in 351 ms.

2011/02/13 0:56:08 org.apache.catalina.ha.session.JvmRouteBinderValve start
情報: JvmRouteBinderValve started

情報: Server startup in 7066 ms
-----

1台目ダウン→2台目のログ
-----
2011/02/13 1:39:41 org.apache.catalina.tribes.group.interceptors.TcpFailureDetector memberDisappeared
情報: Verification complete. Member disappeared[org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000,
alive=2650311,id={80 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]]

2011/02/13 1:39:41 org.apache.catalina.ha.tcp.SimpleTcpCluster memberDisappeared
情報: Received member disappeared:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000, alive=2650311,
id={80 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]
-----

■考察
【Receiver】
Receiverを定義しなくても自動的にポート番号をずらしてListenしている事がわかる。

1台目 - 情報: Receiver Server Socket bound to:/192.168.1.11:4000
2台目 - 情報: Receiver Server Socket bound to:/192.168.1.11:4001

マニュアルにも以下のように説明されている。
「in most cases Tomcat is smart enough to resolve this on it's own by autodetecting available ports in the range 4000-4100」

【メンバ追加】
既に1台目が起動している為、2台目のTomcatは起動時に1台目をメンバに追加。
1台目は2台目が起動した後に1台目をメンバとして追加。

2台目:
2011/02/13 0:56:02 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000, alive=31386,id={8
0 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={}, domain={}, ]

1台目:
2011/02/13 0:56:03 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4001,{192, 168, 1, 11},4001, alive=1042,id={12
4 29 -40 -125 5 -14 72 26 -79 117 60 114 74 -77 21 111 }, payload={}, command={}, domain={}, ]

【JvmRouteの設定】
JvmRouteの設定もよろしくやってくれてそうな気配。
stickysessionにしない場合はあまり関係なさそうだが。

2011/02/13 0:56:08 org.apache.catalina.ha.session.JvmRouteBinderValve start
情報: JvmRouteBinderValve started

【フェイルオーバー】
メンバのダウンを検知している模様。

2011/02/13 1:39:41 org.apache.catalina.tribes.group.interceptors.TcpFailureDetector memberDisappeared
情報: Verification complete. Member

■その他
TomcatではClusterを構成する場合、以下の2つのManagerが利用できる。
デフォルトでは「DeltaManager」を使う設定になっているようだが、Clusterの台数が多くなってくると
パフォーマンスに影響がでそう。

DeltaManager:
全てのメンバでレプリケーションを行う(台数が多いと高負荷)。

BackupManager:
レプリケーション用のノードを1台用意し、そこにセッションをレプリケーションする(単一障害点になるかも)

とりあえず、最低限の定義情報で行ったのでチューニングとかを考えるとまだまだ研究の余地がありそう。

■参考
http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html

TomcatのMIMEタイプの設定

TomcatのMIMEタイプの設定箇所。

【ファイル】
$CATALINA_HOME/conf/web.xml

【記述内容】
<mime-mapping>
  <extension>xls</extension>
  <mime-type>application/x-excel</mime-type>
</mime-mapping>

MIMEマッピング要素に拡張子とタイプを記述。

【環境】
Apache Tomcat6.0
プロフィール

まこち

Author:まこち
スマートフォンのアプリ開発やWebサイト構築等を仕事や趣味でやっています。
最近はグラフデータベースも始めました。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。