多个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.  
  4.           <Manager className="org.apache.catalina.ha.session.DeltaManager" 
  5.                    expireSessionsOnShutdown="false" 
  6.                    notifyListenersOnReplication="true"/> 
  7.  
  8.           <Channel className="org.apache.catalina.tribes.group.GroupChannel"> 
  9.             <Membership className="org.apache.catalina.tribes.membership.McastService" 
  10.                         address="228.0.0.4" 
  11.                         port="45564" 
  12.                         frequency="500" 
  13.                         dropTime="3000"/> 
  14.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
  15.                       address="auto" 
  16.                       port="4000" 
  17.                       autoBind="100" 
  18.                       selectorTimeout="5000" 
  19.                       maxThreads="6"/> 
  20.  
  21.             <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> 
  22.               <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> 
  23.             </Sender> 
  24.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/> 
  25.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/> 
  26.           </Channel> 
  27.  
  28.           <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" 
  29.                  filter=""/> 
  30.           <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> 
  31.  
  32.           <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" 
  33.                     tempDir="/tmp/war-temp/" 
  34.                     deployDir="/tmp/war-deploy/" 
  35.                     watchDir="/tmp/war-listen/" 
  36.                     watchEnabled="false"/> 
  37.  
  38.           <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/> 
  39.           <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> 
  40.         </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.    
  11.   String dataName = request.getParameter("dataName"); 
  12.   if (dataName != null && dataName.length() > 0) { 
  13.      String dataValue = request.getParameter("dataValue"); 
  14.      session.setAttribute(dataName, dataValue); 
  15.      System.out.println("application:" + application.getAttribute(dataName)); 
  16.      application.setAttribute(dataName, dataValue); 
  17.   } 
  18.   out.print("<b>Session List</b>"); 
  19.   Enumeration<String> e = session.getAttributeNames(); 
  20.   while (e.hasMoreElements()) { 
  21.      String name = e.nextElement(); 
  22.      String value = session.getAttribute(name).toString(); 
  23.      out.println( name + " = " + value+"<br>"); 
  24.          System.out.println( name + " = " + value); 
  25.    } 
  26. %> 
  27.   <form action="test.jsp" method="POST"
  28.     Name:<input type=text size=20 name="dataName"
  29.      <br> 
  30.     Value:<input type=text size=20 name="dataValue"
  31.      <br> 
  32.     <input type=submit> 
  33.    </form> 
  34. </body> 
  35. </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复制!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一直以来,我误解认为启动了n个tomcat,则Session需要同步复制到n个Tomcat中存在,因此在启动了6个以上的Tomcat,性能会大大下降。 而实际情况下,采取Apache 加Tomcat进行负载均衡集群的时候,是可以不用将Session复制到所有的节点里, 比如有六个Tomcat实例 Tomcat1,Tomcat2,Tomcat3,Tomcat4,Tomcat5,Tomcat6 是可以配置成 三组互相复制Session的群组, 比如Tomcat1和Tomcat2互相同步Session, 比如Tomcat3和Tomcat4互相同步Session, 比如Tomcat5和Tomcat6互相同步Session. 再在Apache的mod_jk模块里,对每个worker配置上redirect和activation属性。 将Tomcat1,Tomcat3,Tomcat5做为对外正常提供服务器的Tomcat, Tomcat2,Tomcat4,Tomcat6作为分别对应的灾难恢复的备份Tomcat. 即比如Tomcat1当机之后,Apache会自动将发给Tomcat1的请求转发到Tomcat2上, 而Tomcat2因为同步了Tomcat1的Session信息,因此从用户的角度,是感觉不出任何差异的。 单纯的Tomcat测试如下: Tomcat配置: Tomcat1. port=”15080″, jvmRoute=”tomcat1″, <Membership className=”org.apache.catalina.tribes.membership.McastService” address=”228.0.0.5″ port=”45564″ frequency=”500″ dropTime=”3000″/> Tomcat2. port=”16080″, jvmRoute=”tomcat2″, <Membership className=”org.apache.catalina.tribes.membership.McastService” address=”228.0.0.5″ port=”45564″ frequency=”500″ dropTime=”3000″/> Tomcat3. port=”17080″, jvmRoute=”tomcat3″, <Membership className=”org.apache.catalina.tribes.membership.McastService” address=”228.0.0.6″ port=”45564″ frequency=”500″ dropTime=”3000″/> Tomcat4. port=”18080″, jvmRoute=”tomcat4″, <Membership className=”org.apache.catalina.tribes.membership.McastService” address=”228.0.0.6″ port=”45564″ frequency=”500″ dropTime=”3000″/> Tomcat5. port=”19080″, jvmRoute=”tomcat5″, <Membership className=”org.apache.catalina.tribes.membership.McastService” address=”228.0.0.7″ port=”45564″ frequency=”500″ dropTime=”3000″/> Tomcat6. port=”20080″, jvmRoute=”tomcat6″, <Membership className=”org.apache.catalina.tribes.membership.McastService” address=”228.0.0.7″ port=”45564″ frequency=”500″ dropTime=”3000″/> 所有的Tomcat webapp的web.xml加上<distributable /> (例如D:\Java\Tomcat2\webapps\examples\WEB-INF\web.xml ,) 测试页面为: 第一组: http://localhost:15080/examples/servlets/servlet/SessionExample http://localhost:16080/examples/servlets/servlet/SessionExample 第二组: http://localhost:17080/examples/servlets/servlet/SessionExample http://localhost:18080/examples/servlets/servlet/SessionExample 第三组: http://localhost:19080/examples/servlets/servlet/SessionExample http://localhost:20080/examples/servlets/servlet/SessionExample 在每一组中,打开其中任何一个链接,然后设置属性值, 都可以在访问另外一个链接的时候得到。对应的sessionid的后缀会变成对应Tomcat的jvmRoute. (以上测试的tomcat均在同一台服务器上) 接下来再配置Apache的mod_jk. workers.properties的内容节选如下: (重点是redirect和activation两个属性) worker.tomcat1.port=15009 worker.tomcat1.host=127.0.0.1 worker.tomcat1.type=ajp13 worker.tomcat1.lbfactor=1 worker.tomcat1.redirect=tomcat2 worker.tomcat2.port=16009 worker.tomcat2.host=10.108.20.126 worker.tomcat2.type=ajp13 worker.tomcat2.lbfactor=1 worker.tomcat2.redirect=tomcat1 worker.tomcat2.activation=disabled 详细参考: http://tomcat.apache.org/connectors-doc/generic_howto/loadbalancers.html 备注:Tomcat6已经没有使用JGroups来实现集群复制, 而是使用Apache Tribes 来实现该效果的。 Apache Tribes的介绍在: http://tomcat.apache.org/tomcat-6.0-doc/tribes/introduction.html 为了简便配置,因此只使用一份Tomcat,使用不同的cofig来启动,配置好的文件在: http://618119.com/docs/Tomcat/TomcatCluster.zip 下载解压到Tomcat(例如D:\Java\apache-tomcat-6.0.14)目录里,运行对应的bat文件即可: start15080.bat start16080.bat start17080.bat start18080.bat start19080.bat start20080.bat

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值