1. 程式人生 > >多個tomcat之間的session複製

多個tomcat之間的session複製

用tomcat做負載叢集時, 經常會用到session複製(Session Replication), 很多例子會告訴我們要配置apache或者其他的Web Server. 而事實上, 單純從session複製的角度講, 是不需要Web Server的.

tomcat的session複製分為兩種, 一種是全域性試的(all-to-all), 這意味著一個node(tomcat例項)的session發生變化之後, 它會將這些變更復制到其他所有叢集組的成員;另一種是區域性試的, 它會用到BackupManager, BackupManager能實現只複製給一個Buckup Node, 並且這個Node會部署相同的Web應用, 但是這種方式並沒用經過很多的測試

(來自官方說明..).

tomcat的session複製是基於IP組播(multicast)來完成的, 詳細的IP組播介紹可以參考這裡.

簡單的說就是需要進行叢集的tomcat通過配置統一的組播IP和埠來確定一個叢集組, 當一個node的session發生變更的時候, 它會向IP組播發送變更的資料, IP組播會將資料分發給所有組裡的其他成員(node).

配置如下(這裡所有的tomcat都在不同的物理主機, 如果在同一臺主機上需要改tomcat的tcpListenPort)

Xml程式碼  收藏程式碼
  1. <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
      
  2.                  channelSendOptions="8">  
  3.           <Manager className="org.apache.catalina.ha.session.DeltaManager"  
  4.                    expireSessionsOnShutdown="false"  
  5.                    notifyListenersOnReplication="true"/>  
  6.           <Channel className="org.apache.catalina.tribes.group.GroupChannel"
    >  
  7.             <Membership className="org.apache.catalina.tribes.membership.McastService"  
  8.                         address="228.0.0.4"  
  9.                         port="45564"  
  10.                         frequency="500"  
  11.                         dropTime="3000"/>  
  12.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"  
  13.                       address="auto"  
  14.                       port="4000"  
  15.                       autoBind="100"  
  16.                       selectorTimeout="5000"  
  17.                       maxThreads="6"/>  
  18.             <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">  
  19.               <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>  
  20.             </Sender>  
  21.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>  
  22.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>  
  23.           </Channel>  
  24.           <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"  
  25.                  filter=""/>  
  26.           <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>  
  27.           <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"  
  28.                     tempDir="/tmp/war-temp/"  
  29.                     deployDir="/tmp/war-deploy/"  
  30.                     watchDir="/tmp/war-listen/"  
  31.                     watchEnabled="false"/>  
  32.           <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>  
  33.           <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>  
  34.         </Cluster>  

然後新建一個web應用, 我們這裡叫TomcatClusterDemo, web context與名稱一致.

新建一個jsp, 這個jsp複製向session裡建立/更新屬性, 並將session裡的所有屬性顯示在網頁上. 

當然, 為了驗證我們的session是同步的, 我們還將session ID顯示了出來, 程式碼如下:

Jsp程式碼  收藏程式碼
  1.   <%@ page contentType="text/html; charset=UTF-8" %>  
  2. <%@ page import="java.util.*" %>  
  3. <html><head><title>Tomcat Cluster Demo</title></head>  
  4. <body>  
  5. Server Info:  
  6. <%  
  7. out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>  
  8. <%  
  9.   out.println("<br> ID " + session.getId()+"<br>");  
  10.   String dataName = request.getParameter("dataName");  
  11.   if (dataName != null && dataName.length() > 0) {  
  12.      String dataValue = request.getParameter("dataValue");  
  13.      session.setAttribute(dataName, dataValue);  
  14.      System.out.println("application:" + application.getAttribute(dataName));  
  15.      application.setAttribute(dataName, dataValue);  
  16.   }  
  17.   out.print("<b>Session List</b>");  
  18.   Enumeration<String> e = session.getAttributeNames();  
  19.   while (e.hasMoreElements()) {  
  20.      String name = e.nextElement();  
  21.      String value = session.getAttribute(name).toString();  
  22.      out.println( name + " = " + value+"<br>");  
  23.          System.out.println( name + " = " + value);  
  24.    }  
  25. %>  
  26.   <form action="test.jsp" method="POST">  
  27.     Name:<input type=text size=20 name="dataName">  
  28.      <br>  
  29.     Value:<input type=text size=20 name="dataValue">  
  30.      <br>  
  31.     <input type=submit>  
  32.    </form>  
  33. </body>  
  34. </html>  

同時, 在web.xml裡增加<distributable/>描述

Xml程式碼  收藏程式碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  3.     <display-name>TomcatClusterDemo</display-name>  
  4.     <distributable/>  
  5.     <welcome-file-list>  
  6.         <welcome-file>index.html</welcome-file>  
  7.         <welcome-file>index.htm</welcome-file>  
  8.         <welcome-file>index.jsp</welcome-file>  
  9.         <welcome-file>default.html</welcome-file>  
  10.         <welcome-file>default.htm</welcome-file>  
  11.         <welcome-file>test.jsp</welcome-file>  
  12.     </welcome-file-list>  
  13. </web-app>  
 

現在將TomcatClusterDemo部署到兩個tomcat上(直接將war包或者部署檔案拷貝到webapps下, 或者通過Tomcat Web Application Manager部署), 依次啟動兩個tomcat.

先訪問第一臺tomcat(下面的9.119.84.68)的test.jsp, 並新增幾個session.

然後訪問第二臺tomcat(下面的9.119.84.88)的test.jsp, 為了告訴tomcat我們要用那個session訪問, 我們需要在URL後面加上 ;jsessionid=SESSION_ID 

SESSION_ID可以從第一個test.jsp頁面上獲得.

看看效果, 兩個在不同server上的tomcat實現了session複製!