tomcat7集群(session复制)

https://blog.csdn.net/fengwind1/article/details/52163096

tomcat集群的主要方法有三种:

1、采用粘性会话,即某个ip只会访问集群中的某一台机器,这样就可以简单的解决session共享的问题;

2、采用会话共享,目前网上较多的案例是使用memcahed作为共享容器,需要开发以memcahed作为容器的会话管理器,然后配置到tomcat中。

3、采用session复制技术,tomcat本身已支持该功能。

三种方案各有优缺点。第一种存在部分单点问题,如果某台机器崩溃,在此机器的会话将丢失,其他的不受影响;第二种需要额外安装共享容器,如果一台tomcat崩溃,会话仍然可用,但如果会话容器崩溃的话,所有会话都会丢失。对于memcahed,可采用memcached集群方案;第三种方案是tomcat官方介绍的方案,个人感觉只有这个方案真正做到了集群,任何一台tomcat崩溃都不会产生影响,因为是完全备份,这个方案会消耗更多内存和带宽,tomcat官方推荐在集群比较小时采用此方案。

本文介绍第三种方案,参考http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> 
         <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/>                 
         <Channel className="org.apache.catalina.tribes.group.GroupChannel">
           <Membership className="org.apache.catalina.tribes.membership.McastService"  
                       address="228.0.0.4"  
                       port="45564"  
                       frequency="500"  
                       dropTime="3000"/>
           <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"  
                     address="auto"  
                     port="4000"  
                     autoBind="100"  
                     selectorTimeout="5000"  
                     maxThreads="6"/>  
           <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
                <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
           </Sender>
           <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
           <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
         </Channel>
         <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"  
                filter=""/>  
         <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>  
         <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"  
                   tempDir="/tmp/war-temp/"  
                   deployDir="/tmp/war-deploy/"  
                   watchDir="/tmp/war-listen/"  
                   watchEnabled="false"/>
         <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
         <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
      </Cluster>

tomcat集群用的是组播技术,主要需要注意的配置是Membership和Receiver。Membership是组播组,Receiver是接收方。

228.0.0.4是组播地址,这是一个保留地址,关于组播地址,可以查看相关文档。port是端口(可以把Membership当作服务端,Receiver当作客户端,这样就比较好理解)。同一个集群下的机器要加入相同的组播组,所以同一个集群下的tomcat的Membership是一样的。Receiver是接收组播信息的配置,如果两个tomcat在同一个机器,Receiver的port要不相同。如果在不同的机器Receiver的address最好改成ip,如果使用auto,他的值很可能是127.0.0.1,这样会导致接收不到消息。另外,要将Membership和Receiver的端口加入到防火墙中,不然也会无法访问

最后项目的web.xml中需加入<distributable/>以支持集群,关于distributable说明参考

-===================================

 其实就是上述这样的一个架构,下面是原理    

    1)  Apache装有一个模块,这个模块叫mod_jk    
2)  Apache通过80端口负责解析任何静态web内容 

    3)  任何不能解析的内容,用表达式告诉mod_jk,让mod_jk派发给相关的app server去解释。    

    通过上述的文字描述我们可以得知:    

    1) 我们需要在Apache中先装一个mod_jk    

    2) 我们需要在httpd.conf中写点表达式    

    下面来实现。    

    1)  把mod_jk.so手工copy进我们的Apache安装目录的modules目录下    

    下载地址  http://www.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/windows/    

 


 

####### Apache整合Tomcat start #######

    #此处mod_jk的文件为你下载的文件
    LoadModule jk_module modules/mod_jk.so
    #指定tomcat监听配置文件地址
    JKWorkersFile conf/workers.properties
    #指定日志存放位置
    JkLogFile logs/mod_jk.log
    JkLogLevel info

    <VirtualHost localhost>
        ServerAdmin localhost
        DocumentRoot "D:\www"
        ServerName localhost
        
        SetEnv force-proxy-request-1.0.1
        SetEnv proxy-nokeepalive 1
        
        DirectoryIndex index.html index.htm index.jsp index.action
        ErrorLog logs/shsc-error_log.txt
        CustomLog logs/shsc-access_log.txt common
        JkMount /*WEB-INF ajp13
        JkMount /*j_spring_security_check ajp13
        JkMount /*.action ajp13
        JkMount /servlet/* ajp13
        JkMount /*.jsp ajp13
        JkMount /*.do ajp13
        JkMount /*.action ajp13
        JkMount /*fckeditor/editor/filemanager/connectors/*.* ajp13
        JkMount /fckeditor/editor/filemanager/connectors/* ajp13
    </VirtualHost>

    ####### Apache整合Tomcat end #######


    


    Apache    conf
    目录下 建个    workers.properties
    文件 内容如下: 


 
   
     

ps=    worker.list=ajp13 #模块版本
    worker.ajp13.port=8009 #工作端口,若没占用则不用修改
    worker.ajp13.host=localhost #本机,若上面的Apache主机不为localhost,作相应修改
    worker.ajp13.type=ajp13 #类型
    #worker.ajp13.lbfactor=1 #代理数,不用修改


             

   
 
 


    

    集群配置 tomcat6
    

    第一种,simple tcp cluster (tomcat5以上版本自带的基于tcp广播技术的集群,这种方法比较简单,只需修改server.xml配置文件即可)    

    在<Engine></Engine>添加如下配置代码,多台机器,只需修改第二个 address (本机地址)和port 即可。 


 

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

  <Manager className="org.apache.catalina.ha.session.BackupManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true" mapSendOptions="6" />
  <!--
    <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/>
  -->
  <Channel className="org.apache.catalina.tribes.group.GroupChannel">
    <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000" />
    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="   192.168.67.143" port="   4001" selectorTimeout="100" maxThreads="6" />

    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
      <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
    </Sender>
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor" />
    <Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor" />
  </Channel>

  <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;" />
  <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" />

  <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false" />

  <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />
  <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />


 


      注意:在 Tomcat的集群复制中,分为DeltaManager和BackupManager两种,前者适合于小型系统,任何情况下,均进行Session复 制,消耗大量资源。所以,我们应该采用BackupManager,仅在需要的时候(Tomcat挂掉的时候)进行Session复制。如果是在同一台机器上配置多个tomcat实例来进行集群的测试,那么请一定要注意tomcat实例运行的端口和 集群所监听的端口是否冲突!    

    
      

    

    
    最后修改web应用WEB-INF目录下的    web.xml
    文件 在    </web-app>
    前加    <distributable />
    

       标签(这个是tomcat进行session复制所必须的,否则session不能进行复制!)    

          或者
    改变Tomcat的content.xml配置文件,修改 <Context distributable="true">    

 


 

   tomcat的集群部署修改动作都比较简单,但实际在运行过程中会出现一系列的问题,我这里列举我在配置后使用过程中出现的一些问题和要点,供大家参考:


 

1、用户存入SESSION中的数据的问题


 

      使用tomcat集群进行SESSION复制,必须要保证你的session中存放的所有对象都是实现了java.io.Serializable接口 的,因为session复制就是序列化对象到其他WEB应用服务器上的,所以如果没有实现该接口,那么SESSION同步将会失败。另外一点,就是如果要 同步的机器比较多的话,那么要注意保证SESSION中存放的数据比较小,不要什么都存放到SESSION中,因为复制SESSION也是需要开销的,数 据越大开销也越大。


 

2、Tomcat执行SESSION复制的触发条件


 

      我们在tomcat的server.xml文件中集群部分cluster标签中可以看到属性:useDirtyFlag, 如果这个设置为true(默认的),那么只有当使用setAttribute往session中设置数据的时候才会同步其他WEB服务器的 SESSION,如果为false,那么每一次请求的sesison都会被同步到其他服务器上。因此在操作SESSION的时候要特别注意,避免出现 SESSION无法同步的问题。


 

      举个简单的例子,比如我们在单机应用情况下修改SESSION中用户的某一个数据,那么通常就是:


 
   
     
         

User user = (User)request.getSession().getAttribute(“user”);         

User.setName(“my name”); 

 

      这样我们就是直接存取出来,然后进行修改,虽然在单机情况下没有问题,但是在集群条件下,这样就导致了多台WEB服务器上的SESSION不同步的问 题,因为SESSION并没有改变,Tomcat无法监视session中某个数据的值是否发生了变化。因此,我们还需要执行如下操作以保证 SESSION的同步:
         

request.getSession().setAttribute(“user”, user);

      所以,我们在操作SESSION的时候要特别注意!另外的建议就是,我们应该尽可能的不要修改SESSION中的数据。

      因为Tomcat的SESSION复制通信是通过组播功能来实现不同服务器之间的交互的,所以需要在服务器上开通组播功能,windows默认情况下是开通组播服务的,而Linux系统下默认是没有开通的,我们需要通过如下命令来开通其组播功能:

         

route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

 如果需要服务器启动时即开通组播需在/etc/sysconfig/static-routes文件内加入eht0 net 224.0.0.0 netmask 240.0.0.0。具体组播概念请查阅CCNP相关内容。


    可以通过netstate -g 来查看组播状态,也可以在route -e 命令中看到    
        
    第二种,使用memcached共享session    

    memcached-session-manager 配置    

    让tomcat 调用memcached 来存储session 早就是一个很成熟的解决方案了,开源的msm 就可以解决这个问题。    

    官方给出的4 种序列化方案,其中kryo 是效率最高的,具体比较看官方地址:    

    http://code.google.com/p/memcached-session-manager/wiki/SerializationStrategies    

    下载地址:    

    http://code.google.com/p/memcached-session-manager/downloads/list    

    本次实验用的tomcat版本为6.0.18,以下为我用包,,谁有需要可以联系我,(高版本的自己测试如果不报错,,就可以直接用)    

    kryo-1.03.jar    

    reflectasm-0.9.jar    

    minlog-1.2.jar    

    kryo-serializers-0.8.jar    

    memcached-2.5.jar    

    memcached-session-manager-tc7-1.5.1.jar    

    msm-kryo-serializer-1.5.1.jar    

    memcached-session-manager-1.5.1.jar    

    把以上8个包丢在tomcat的lib文件夹    

    修 改Tomcat的配置文件context.xml,调整成新的session存储方式,在配置文件中<context>标签内加入一下代码 (如果memcached跟tomcat不在同一台机器,修改127.0.0.1为memcached所在机器的IP):    

   
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"    

    memcachedNodes="n1:127.0.0.1:11211"    

    sticky="false"    

    lockingMode="auto"    

    sessionBackupAsync="false"    

    sessionBackupTimeout="1000"    

    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"    

    />    

    在tomcat/conf/logging.properties 文件中添加de.javakaffee.web.msm.level=FINE , 就可以在    

    catalina.out 的日志中看到详细的session 存取情况。    

         

    一般前边还有Nginx做转发,分发给不同机器的tomcat上面,,    tomcat集群(共享session)
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值