Chinaunix首页 | 论坛 | 博客
  • 博客访问: 630856
  • 博文数量: 244
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-27 09:53
个人简介

记录学习,记录成长

文章分类

全部博文(244)

我的朋友

分类: LINUX

2016-05-13 09:08:01

一.tomcat会话管理
1.声明
对于WEB应用集群的技术实现而言,最大的难点就是如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块。要实现这一点,大体上有两种方式,一种是把所有Session数据放到一台服务器上或者数据库中,集群中的所有节点通过访问这台Session服务器来获取数据;另一种就是在集群中的所有节点间进行Session数据的同步拷贝,任何一个节点均保存了所有的Session数据。
两种方式都各有优点,第一种方式简单、易于实现,但是存在着Session服务器发生故障会导致全系统不能正常工作的风险;第二种方式可靠性更高,任一节点的故障不会对整个系统对客户访问的响应产生影响,但是技术实现上更复杂一些。
tomcat提供了这两种session共享的支持,但是tomcat一般采用第二种;


2.session管理机制
会话管理器定义:Session管理器组件负责管理Session对象,例如,创建和销毁Session对象。

(1)Manager:定义了关联到某一个容器的用来管理session池的基本接口。

(2)ManagerBase:实现了Manager接口,该类提供了Session管理器的常见功能的实现。


(3)StandardManager:继承自ManagerBase,tomcat的默认Session管理器(不指定配置,默认使用这个),是tomcat处理session的非集群实现(也就说是单机版的),tomcat关闭时,内存session信息会持久化到磁盘保存为SESSION.ser,再次启动时恢复。


(4)PersistentManagerBase:继承自ManagerBase,实现了和定义了session管理器持久化的基础功能。


(5)PersistentManager:继承自PersistentManagerBase,主要实现的功能是会把空闲的会话对象(通过设定超时时间)交换到磁盘上。


(6)ClusterManager:实现了Manager接口,通过类名应该能猜到,这个就是管理集群session的管理器和上面那个StandardManager单机版的session管理器是相对的概念。这个类定义类集群间session的复制共享接口。


(7)ClusterManagerBase:实现了ClusterManager接口,继承自ManagerBase。该类实现了session复制的基本操作。


(8)BackupManager:继承自ClusterManagerBase,集群间session复制策略的一种实现,会话数据只有一个备份节点,这个备份节点的位置集群中所有节点都可见。这种设计使它有个优势就是支持异构部署。


(9)DeltaManager:继承自ClusterManagerBase,集群建session复制策略的一种实现,和BackupManager不同的是,会话数据会复制到集群中所有的成员节点,这也就要求集群中所有节点必须同构,必须部署相同的应用。


3.Manager
会话管理组件Manger对象用于实现HTTP会话管理的功能,其有5种Manger的实现:

(1)标准会话管理器StandardManager:
Tomcat7的默认会话管理器,用于非集群环境中对单个处于运行状态的Tomcat实例会话进行管理。当Tomcat关闭时,这些会话相关的数据会被写入磁盘上的一个名叫SESSION.ser的文件中,并在Tomcat下次启动时读取此文件。
    默认只有在Tomcat正常关闭时才会保存完整的用户会话信息,异常关闭时则不会保存下来;

    默认保存于$CATALINA_HOME/work/Catalina///下的SESSIONS.ser文件中;

    若是自定义的虚拟主机则保存在$CATALINA_HOME/work/Catalina//_/ 下的 SESSIONS.ser 文件中;
定义:
  1. <Manager className="org.apache.catalina.session.StandardManager" maxInactiveInterval="7200"/>
可用属性:
        maxActiveSessions:最多允许的活动会话数量,默认为-1,表示不限制; 
        maxInactiveInterval:非活动的会话超时时长,默认为60s;
        pathname:会话文件的保存目录;

(2).持久会话管理器PersistentManager
将会话数据保存至持久存储中,并且能在服务器意外中止后重新启动时重新加载这些会话信息。持久会话管理器支持将会话保存至文件存储(FileStore)或JDBC存储(JDBCStore)中。当一个会话长时间处于空闲状态(超过设定的时间)时会被写入到swap会话对象,这对于内存资源比较吃紧的应用环境来说比较有用。和标准会话管理器一样,都是用在tomcat单实例的会话管理器;

保存至文件中的示例:
  1. <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
  2.          <Store className="org.apache.catalina.session.FileStore" directory="/session/tomcat"/>
  3.         </Manager>
         每个用户的会话会被保存至directory指定的目录中的文件中,文件名为.session,并通过后台线程每隔一段时间(checkInterval参数定义,默认为60秒)检查一次超时会话;

保存至JDBCStore中的示例:
  1. <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
  2.          <Store className="org.apache.catalina.session.JDBCStore" driverName="com.mysql.jdbc.Driver"
  3.          connectionURL="jdbc:mysql://localhost:3306/mydb?user=jb;password=pw"/>
  4.         </Manager>
补充:
PersistentManagerBase类中有个成员变量Store,持久化session管理器的存储策略就是有这个Store对象定义的,这个Store的类继承结构如下:

简述:接口Store及其实例是为session管理器提供了一套存储策略,store定义了基本的接口,而StoreBase提供了基本的实现。其中FileStore类实现的策略是将session存储在以setDirectory()指定目录并以.session结尾的文件中的。JDBCStore类是将Session通过JDBC存入数据库中,因此需要使用JDBCStore,需要分别调用setDriverName()方法和setConnectionURL()方法来设置驱动程序名称和连接URL。


(3)DeltaManager
用于Tomcat集群(复制集群)的会话管理器,它通过将改变了的会话数据同步给集群中的其它节点以实现会话复制。这种实现会将所有会话的改变同步给集群中的每一个节点,也是在集群环境中用得最多的一种实现方式。这个管理器仅适用于小的架构模型,因为太多的节点间会话复制会消耗很多的系统资源,较大的一般都使用session服务器;


(4)BackupManager
用于Tomcat集群的会话管理器,与DeltaManager不同的是,某节点会话的改变只会同步给集群中的另一个而非所有节点;


5)SimpleTcpReplicationManager
最初设计该集群会话管理器是为了Tomcat 4和最早的实现,Tomcat委员会建议使用DeltaManager替代这一管理器;


二.配置tomcat的session复制集群
接着上一次的负载均衡继续配置(mod_proxy):http://blog.chinaunix.net/uid-30212356-id-5718697.html
配置环境:
前端:192.168.85.128+Apache
后端1:192.168.85.129+tomcat
后端2:192.168.85.130+tomcat

上一次虽然做了tomcat的负载均衡,保证了用户的请求能始终在同一台tomcat上,但是用户的会话还是在时刻变着的,接下来要做的就是要保证用户会话(sessionid)保持不变;
负载均衡时:

刷新页面:


但是在基于负载均衡的同时加上会话保持(stickysession=JSESSIONID)时,用户会话的sessionid就不会变!
负载均衡+会话保持时:

刷新页面:

1.跟集群相关的组件(摘自马哥笔记)
Stores:PersistentManager必须包含一个Store元素以指定将会话数据存储至何处。这通常有两种实现方式:FileStore和JDBCStore。


Resources:经常用于实现在Context中指定需要装载的但不在Tomcat本地磁盘上的应用资源如Java类,HTML页面,JSP文件等。


Cluster:专用于配置Tomcat集群的元素,可用于Engine和Host容器中。在用于Engine容器中时,Engine中的所有Host均支持集群功能。在Cluster元素中,需要直接定义一个Manager元素,这个Manager元素有一个其值为org.apache.catalina.ha.session.DeltaManager或org.apache.catalina.ha.session.BackupManager的className属性。同时,Cluster中还需要分别定义一个Channel和ClusterListener元素。


Channel:用于Cluster中给集群中同一组中的节点定义通信“信道”。Channel中需要至少定义Membership、Receiver和Sender三个元素,此外还有一个可选元素Interceptor。


Membership:用于Channel中配置同一通信信道上节点集群组中的成员情况,即监控加入当前集群组中的节点并在各节点间传递心跳信息,而且可以在接收不到某成员的心跳信息时将其从集群节点中移除。Tomcat6中Membership的实现是org.apache.catalina.tribes.membership.McastService。


Sender:用于Channel中配置“复制信息”的发送器,实现发送需要同步给其它节点的数据至集群中的其它节点。发送器不需要属性的定义,但可以在其内部定义一个Transport元素。


Transport:用于Sender内部,配置数据如何发送至集群中的其它节点。Tomcat6有两种Transport的实现:
        1) PooledMultiSender
        基于Java阻塞式IO,可以将一次将多个信息并发发送至其它节点,但一次只能传送给一个节点。

        2)PooledParallelSener
        基于Java非阻塞式IO,即NIO,可以一次发送多个信息至一个或多个节点。


Receiver:用于Channel定义某节点如何从其它节点的Sender接收复制数据,Tomcat6中实现的接收方式有两种BioReceiver和NioReceiver。


2.默认集群配置(此部分摘自网络,仅供参考)
tomcat7默认的集群配置如下,其配置细节实际上被忽略了
  1. <!--
  2.     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
  3. -->
而完整的默认配置如下(对于大多数应用而言,使用默认配置已经足够):

  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>
解释说明:
tomcat集群各节点通过建立tcp链接来完成Session的拷贝,拷贝有同步和异步两种模式。
在同步模式下,对客户端的响应必须在Session拷贝到其他节点完成后进行;异步模式无需等待Session拷贝完成就可响应。异步模式更高效,但是同步模式可靠性更高。
同步异步模式由channelSendOptions参数控制,默认值是8,为异步模式,4是同步模式。在异步模式下,可以通过加上拷贝确认(Acknowledge)来提高可靠性,此时channelSendOptions设为10。
 
Manager用来在节点间拷贝Session,默认使用DeltaManager,DeltaManager采用的一种all-to-all的工作方式,即集群中的节点会把Session数据向所有其他节点拷贝,而不管其他节点是否部署了当前应用。
当集群中的节点数量很多并且部署着不同应用时,可以使用BackupManager,BackManager仅向部署了当前应用的节点拷贝Session。但是到目前为止BackupManager并未经过大规模测试,可靠性不及DeltaManager。
 
Channel负责对tomcat集群的IO层进行配置。


Membership用于发现集群中的其他节点,这里的address用的是组播地址(Multicastaddress,使用同一个组播地址和端口的多个节点同属一个子集群,因此通过自定义组播地址和端口就可将一个大的tomcat集群分成多个子集群。


Receiver用于各个节点接收其他节点发送的数据,在默认配置下tomcat会从4000-4100间依次选取一个可用的端口进行接收,自定义配置时,如果多个tomcat节点在一台物理服务器上,注意要使用不同的端口。


Sender用于向其他节点发送数据,具体实现通过Transport配置,PooledParallelSender是从tcp连接池中获取连接,可以实现并行发送,即集群中的多个节点可以同时向其他所有节点发送数据而互不影响。


Interceptor有点类似下面将要解释的Valve,起到一个阀门的作用,在数据到达目的节点前进行检测或其他操作,如TcpFailureDetector用于检测在数据的传输过程中是否发生了tcp错误。关于Channel的编程模型,请参考
 
Valve用于在节点向客户端响应前进行检测或进行某些操作,ReplicationValve就是用于用于检测当前的响应是否涉及Session数据的更新,如果是则启动Session拷贝操作,filter用于过滤请求,如客户端对图片,css,js的请求就不会涉及Session,因此不需检测,默认状态下不进行过滤,监测所有的响应。


JvmRouteBinderValve会在前端Apache的mod_jk发生错误时保证同一客户端的请求发送到集群的同一个节点,tomcat官方文档并未解释如何实现这一点,而且笔者认为这一设置似乎并无多大实用性。
 
Deployer用于集群的farm功能,监控应用中文件的更新,以保证集群中所有节点应用的一致性,如某个用户上传文件到集群中某个节点的应用程序目录下,Deployer会监测到这一操作并把这一文件拷贝到集群中其他节点相同应用的对应目录下以保持所有应用的一致。这是一个相当强大的功能,不过很遗憾,tomcat集群目前并不能做到这一点,开发人员正在努力实现它,这里的配置只是预留了一个接口。
 
ClusterListener用于跟踪集群中节点发出和收到的数据,也有点类似Valve的功能。


下面通过假想的一组场景来描述tomcat集群如何工作,集群采用默认配置,由t1和t2两个tomcat例程组成,场景按照时间顺序排列。
1. t1启动
    t1按照标准的tomcat启动,当Host对象被创建时,一个Cluster对象(默认配置下是SimpleTcpCluster)也同时被关联到这个Host对象。当某个应用在web.xml中设置了distributable时,Tomcat将为此应用的上下文环境创建一个DeltaManager。SimpleTcpCluster启动membership服务和Replication服务(用于建立tcp连接)。


2. t2启动(待t1启动完成后)
    首先t2会执行和t1一样的操作,然后SimpleTcpCluster会建立一个由t1和t2组成的membership。接着t2向集群中已启动的服务器即t1请求Session数据,如果t1没有响应t2的拷贝请求,t2会在60秒后time out。在Session数据拷贝完成之前t2不会接收客户端的http或mod_jk/ajp请求。


3. t1接收http请求,创建Session s1
    t1正常响应客户请求,但是在t1把结果发送回客户端时,ReplicationValve会拦截当前请求(如果filter中配置了不需拦截的请求类型,这一步就不会进行,默认配置下拦截所有请求),如果发现当前请求更新了Session,调用Replication服务建立tcp连接把Session拷贝到membership列表中的其他节点即t2,返回结果给客户端(注意,如果采用同步拷贝,必须等拷贝完成后才会返回结果,异步拷贝在数据发送到tcp连接就返回结果,不等待拷贝完成)。在拷贝时,所有保存在当前Session中的可序列化的对象都会被拷贝,而不仅仅是发生更新的部分。


4. t1崩溃
    当t1崩溃时,t2会被告知t1已从集群中退出,然后t2就会把t1从自己的membership列表中删除,发生在t2的Session更新不再往t1拷贝,同时负载均衡器会把后续的http请求全部转发给t2。在此过程中所有的Session数据不会丢失。


5. t2接收s1的请求
    t2正常响应s1的请求,因为t2保存着s1的所有数据。


6. t1重新启动
    按步骤1、2一样的操作启动,加入集群,从t2拷贝所有Session数据,拷贝完成后开放自己的http和mod_jk/ajp端口接收请求。


7. t1接收请求,s1失效
    t1继续接收来自s1的请求,把s1设置为过期。这里的过期并非因为s1处于非活动状态超过设置的时间,而是执行类似注销的操作而引起的Session失效。这时t1并非发送s1的所有数据而是一个类似s1 expired的消息,t2收到消息后也会把s1设为过期。


8. t2接收请求,创建Session s2
    和步骤3一样。


9. t1 s2过期
    对于因超时引起的Session失效t1无需通知t2,因为t2同样知道s2已经超时。因此对于tomcat集群有一点非常重要,所有节点的操作系统时间必须一致!不然会出现某个节点Session已过期而在另一节点此Session仍处于活动状态的现象。


补充:
Membership 中:
            address:指定多播地址;
            port:指定端口号;
            frequency:节点间心跳信息传送的频率;
            dropTime:设置节点为不可用节点的超时时间;

Receiver中:
            address:在哪个地址上完成心跳信息传递和节点数据传输;
            port:指定端口号;
            autoBind:自动绑定,一次性可以接受多少个;
            selectorTimeout:挑选(如节点是否可用)的超时时间;
            maxThreads:最大线程数;

如果对整体的Enige做cluster就将上述配置放到Enige中,如果只对特定的主机做cluster就放到特定的Host中;

3.具体配置
3.1编辑配置文件
tomcatA的server.xml文件内容如下:
[root@localhost conf]# cat server.xml
  1. <?xml version='1.0' encoding='utf-8'?>
  2. <Server port="8005" shutdown="SHUTDOWN">
  3.   <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  4.   <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  5.   <Listener className="org.apache.catalina.core.JasperListener" />
  6.   <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  7.   <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  8.   <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  9.   <GlobalNamingResources>
  10.     <Resource name="UserDatabase" auth="Container"
  11.               type="org.apache.catalina.UserDatabase"
  12.               description="User database that can be updated and saved"
  13.               factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
  14.               pathname="conf/tomcat-users.xml" />
  15.   </GlobalNamingResources>

  16.   <Service name="Catalina">

  17.     <Connector port="80" address="192.168.85.129" maxThreads="1024"
  18.                protocol="org.apache.coyote.http11.Http11AprProtocol"
  19.                connectionTimeout="60000"
  20.                redirectPort="443" />

  21.     <Connector port="8009" protocol="AJP/1.3" redirectPort="443" />

  22.     <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatA">
  23.     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
  24.                  channelSendOptions="8">
  25.           <Manager className="org.apache.catalina.ha.session.DeltaManager"
  26.                    expireSessionsOnShutdown="false"
  27.                    notifyListenersOnReplication="true"/>
  28.           <Channel className="org.apache.catalina.tribes.group.GroupChannel">
  29.             <Membership className="org.apache.catalina.tribes.membership.McastService"
  30.                         address="228.0.100.4"
  31.                         port="45564"
  32.                         frequency="500"
  33.                         dropTime="3000"/>
  34.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
  35.                       address="192.168.85.129"
  36.                       port="4000"
  37.                       autoBind="100"
  38.                       selectorTimeout="5000"
  39.                       maxThreads="6"/>
  40.             <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
  41.               <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
  42.             </Sender>
  43.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
  44.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
  45.           </Channel>
  46.           <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
  47.           <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
  48.           <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
  49.                     tempDir="/tmp/war-temp/"
  50.                     deployDir="/tmp/war-deploy/"
  51.                     watchDir="/tmp/war-listen/"
  52.                     watchEnabled="false"/>
  53.           <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
  54.           <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
  55.     </Cluster>
  56.       <Realm className="org.apache.catalina.realm.LockOutRealm">
  57.         <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
  58.                resourceName="UserDatabase"/>
  59.       </Realm>
  60.       <Host name="localhost" appBase="webapps"
  61.             unpackWARs="true" autoDeploy="true">
  62.         <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
  63.                prefix="localhost_access_log." suffix=".txt"
  64.                pattern="%h %l %u %t "%r" %s %b" />
  65.       </Host>
  66.     </Engine>
  67.   </Service>
  68. </Server>
tomcatB的server.xml文件内容如下:
[root@localhost conf]# cat server.xml
  1. <?xml version='1.0' encoding='utf-8'?>
  2. <Server port="8005" shutdown="SHUTDOWN">
  3.   <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  4.   <!-- Security listener. Documentation at /docs/config/listeners.html
  5.   <Listener className="org.apache.catalina.security.SecurityListener" />
  6.   <Listener className="org.apache.catalina.core.JasperListener" />
  7.   <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  8.   <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  9.   <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  10.   <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  11.   <GlobalNamingResources>
  12.     <Resource name="UserDatabase" auth="Container"
  13.               type="org.apache.catalina.UserDatabase"
  14.               description="User database that can be updated and saved"
  15.               factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
  16.               pathname="conf/tomcat-users.xml" />
  17.   </GlobalNamingResources>
  18.   <Service name="Catalina">
  19.     <Connector port="80" address="192.168.85.130" protocol="HTTP/1.1"
  20.                connectionTimeout="20000"
  21.                redirectPort="8443" />
  22.     <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
  23.     <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatB">
  24.     <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
  25.                  channelSendOptions="8">
  26.           <Manager className="org.apache.catalina.ha.session.DeltaManager"
  27.                    expireSessionsOnShutdown="false"
  28.                    notifyListenersOnReplication="true"/>
  29.           <Channel className="org.apache.catalina.tribes.group.GroupChannel">
  30.             <Membership className="org.apache.catalina.tribes.membership.McastService"
  31.                         address="228.0.100.4"
  32.                         port="45564"
  33.                         frequency="500"
  34.                         dropTime="3000"/>
  35.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
  36.                       address="192.168.85.130"
  37.                       port="4000"
  38.                       autoBind="100"
  39.                       selectorTimeout="5000"
  40.                       maxThreads="6"/>
  41.             <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
  42.               <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
  43.             </Sender>
  44.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
  45.             <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Intercepto"/>
  46.           </Channel>
  47.           <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
  48.           <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
  49.           <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
  50.                     tempDir="/tmp/war-temp/"
  51.                     deployDir="/tmp/war-deploy/"
  52.                     watchDir="/tmp/war-listen/"
  53.                     watchEnabled="false"/>
  54.           <ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
  55.           <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
  56.     </Cluster>
  57.       <Realm className="org.apache.catalina.realm.LockOutRealm">
  58.         <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
  59.                resourceName="UserDatabase"/>
  60.       </Realm>
  61.       <Host name="localhost" appBase="webapps"
  62.             unpackWARs="true" autoDeploy="true">
  63.         <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
  64.                prefix="localhost_access_log." suffix=".txt"
  65.                pattern="%h %l %u %t "%r" %s %b" />

  66.       </Host>
  67.     </Engine>
  68.   </Service>
  69. </Server>
3.2编辑web.xml文件
根据tomcat7.0官方资料中的说明,有这么一句话
Make sure your web.xml has the <distributable/>element,继续配置各节点的web.xml,使tomcatA和tomcatB的web.xml文件中加上一句;

3.3检查语法并重启tomcat后测试
注意:
如果出错请查看日志catalina.out,我也出现了错误,查看官方文档才知道是我的两个tomcat时间不一致:
Make sure that all nodes have the same time and sync with NTP service! #时间同步

Make sure that your loadbalancer is configured for sticky session mode. #负载均衡要配置会话保持

而且有时有必要在各节点为使用组播地址添加组播路由,格式为:
route add -net 组播地址 netmask 255.255.255.255 dev eth0

测试结果:
无论怎么刷新,都是一个页面



参考文档:


http://zyycaesar.iteye.com/blog/296606


阅读(2305) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~