`

[转]Tomcat集群Cluster实现原理剖析

阅读更多

 

 

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

 

     当采用tomcat默认集群配置(<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>)时,配置的细节实际上被 省略了,对于大多数应用而言,使用默认配置已经足够,完整的默认配置应该是这样:

 

     <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官方文档后自己的理解,有些可能不对,希望读者能带着批判的眼光阅读,并欢迎指正笔者错误。

 

     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用的是组播地址(Multicast address,了解更多组播地址详情请参见http://up2u.iteye.com/blog/793926 ), 使用同一个组播地址和端口的多个节点同属一个子集群,因此通过自定义组播地址和端口就可将一个大的tomcat集群分成多个子集群 。Receiver用于 各个节点接收其他节点发送的数据,在默认配置下tomcat会从4000-4100间依次选取一个可用的端口进行接收,自定义配置时,如果多个 tomcat节点在一台物理服务器上注意要使用不同的端口。Sender用于向其他节点发送数据,具体实现通过Transport配 置,PooledParallelSender是从tcp连接池中获取连接,可以实现并行发送,即集群中的多个节点可以同时向其他所有节点发送数据而互不 影响。Interceptor有点类似下面将要解释的Valve,起到一个阀门的作用,在数据到达目的节点前进行检测或其他操作,如 TcpFailureDetector用于检测在数据的传输过程中是否发生了tcp错误。关于Channel的编程模型,请参见http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/tribes/Channel.html

 

     Valve用于在节点向客户端响应前进行检测或进行某些操作,ReplicationValve就是用于用于检测当前的响应是否涉及Session数据的 更新,如果是则启动Session拷贝操作,filter用于过滤请求,如客户端对图片,css,js的请求就不会涉及Session,因此不需检测,默 认状态下不进行过滤,监测所有的响应。JvmRouteBinderValve会在前端的Apache mod_jk发生错误时保证同一客户端的请求发送到集群的同一个节点,tomcat官方文档并未解释如何实现这一点,而且笔者认为这一设置似乎并无多大实 用性。

 

     Deployer用于集群的farm功能,监控应用中文件的更新,以保证集群中所有节点应用的一致性,如某个用户上传文件到集群中某个节点的应用程序目录 下,Deployer会监测到这一操作并把这一文件拷贝到集群中其他节点相同应用的对应目录下以保持所有应用的一致。这是一个相当强大的功能,不过很遗 憾,tomcat集群目前并不能做到这一点,开发人员正在努力实现它,这里的配置只是预留了一个接口。

 

    Listener用于跟踪集群中节点发出和收到的数据,也有点类似Valve的功能。

 

    在大体了解了tomcat集群实现模型后,就可以对集群作出更优化的配置了,tomcat推荐了一套配置,使用了比DeltaManager更高效的 BackupManager,并且对ReplicationValve设置了请求过滤,注意在一台服务器部署多个节点时需要修改Receiver的侦听端 口,另外,为了更高效的在节点间拷贝数据,所有tomcat节点最好采用相同的配置,具体配置如下:

 

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

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


          <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="5000"
                      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;"/>

          <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.ClusterSessionListener"/>
        </Cluster>

 

     Tomcat集群除了可以进行Session数据的拷贝,还可进行Context属性的拷贝,通过修改context.xml的Context配置可以实 现,使用<Context className="org.apache.catalina.ha.context.ReplicatedContext"/>替换默认 Context即可,当然也可再加上distributable="true"属性。

 

     下面通过假想的一组场景来描述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仍处于活动状态的现象。

 

 

分享到:
评论
1 楼 tdqing 2012-02-13  
记录一下:

   Apache + Tomcat + Linux 集群和均衡负载 (Session 同步复制) 配置实践指南

    经过我的多次测试实践,在linux和window下测试通过,win的比较简单,因为在默认的情况下,组播就已经打开。
    1 在linux 下同一台服务器上测试通过(注意端口不要冲突。特别要注意那个tcpListenPort=”4001″ )
    2 在window下的同一台服务器上测试通过,注意要点同上
    3 window下多台不同主机上测试通过,没有什么好注意点,可以完全备份一个tomcat
    4.linux多台不同tomcat服务器上测试通过。这个也是最后实现,最实际的方案。(一般不用在win下部署tomcatweb应用。呵呵。我觉得)

    这里讲下第四中情况
    先讲一下环境:都是在Red Hat Linux AS4上测试通过
    Apache:ip:192.168.1.11 (一台) 版本:2.0/2.2 (做均换负载服务器)
    Tomcat:ip1:192.168.1.12 ip2:192.168.1.13 (两台) 版本:5.0、5.5 (web应用的Real Server)
    Jdk:版本1.5 安装在 192.168.1.12 和192.168.1.13上的tomcat服务器上
    安装tomcat和apache ,在这里就不讲了。
    软件都可以在www.apache.org 的网站上找到(apache,tomcat,mod_jk)
    1.下载mod_jk.so 文件放到apache 下的modules下
    地址:http://apache.mirror.phpchina.com/tomcat/tomcat-connectors/jk/binaries/ 请选择正确的操作系统和Apache的版本。
    2.在apache的conf下建立文件workers.properties
    添加内容:
    #
    # workers.properties
    #
    # list the workers by name
    worker.list=tomcatlb, status
    # localhost server 1
    # ------------------------
    worker.tomcat12.port=8009
    worker.tomcat12.host=192.168.1.12
    worker.tomcat12.type=ajp13
    worker.tomcat12.lbfactor=1
    worker.tomcat12.connection_pool_timeout=750
    worker.tomcat12.socket_keepalive=0
    worker.tomcat12.socket_timeout=300000
    worker.tomcat12.connect_timeout=10000
    worker.tomcat12.reply_timeout=330000
    # localhost server 3
    # ------------------------
    worker.tomcat13.port=8009
    worker.tomcat13.host=192.168.1.13
    worker.tomcat13.type=ajp13
    worker.tomcat13.lbfactor=1
    worker.tomcat13.connection_pool_timeout=750
    worker.tomcat13.socket_keepalive=0
    worker.tomcat13.socket_timeout=300000
    worker.tomcat13.connect_timeout=10000
    worker.tomcat13.reply_timeout=330000
    worker.tomcatlb.type=lb
    worker.retries=3
    worker.tomcatlb.balanced_workers=tomcat12,tomcat13
    worker.tomcatlb.sticky_session=1
    worker.status.type=status
    3.在conf下添加一个mod_jk.conf文件
    LoadModule    jk_module  modules/mod_jk.so
    #configure mod_jk
    JkWorkersFile conf/workers.properties
    JkLogFile logs/mod_jk.log
    JkLogLevel debug
4.增加一个虚拟机配置文件vhosts.conf (这个不是必须的,可以将JkMount 的写其他的配置文件中)
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /data/google
    ServerName my.linuxcoffee.org
    ErrorLog logs/my.linuxcoffee.org-error_log
    CustomLog logs/my.linuxcoffee.org-access_log common
    DirectoryIndex index.htm  index.html
    JkMount /*.jsp tomcatlb
    JkMount /*.action tomcatlb
    JKMount /jkstatus status

    4.修改conf下的httpd.conf文件加上
    Include conf/vhosts.conf
    Include conf/mod_jk.conf

    5.配置tomcat
    讲Cluster 前的注释去掉,启用tomcat集群功能。
    一般不需要修改什么东西,但在我这边,两台linux的tomcat就是死活找不到node,而同样的配置文件在window下的跑得很是正常。
    有个东西要说明下,因为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 命令中看到
    原来一直提示这个问题
    信息: Manager [/clusterapp]: skipping state transfer. No members active in cluster group.
    最后测试只要修改在Cluster之间的一段代码
    Receiver
    className="org.apache.catalina.cluster.tcp.ReplicationListener"
    tcpListenAddress="auto"
    tcpListenPort="4001"
    tcpSelectorTimeout="100"
    tcpThreadCount="6"/>

    改为

    Receiver
    className="org.apache.catalina.cluster.tcp.ReplicationListener"
    tcpListenAddress="192.168.1.12"
    tcpListenPort="4001"
    tcpSelectorTimeout="100"
    tcpThreadCount="6"/>

    在13的服务器上也将这一段修改为自己的ip
    然后打开jvmRoute ,跟workers.properties 的两个tomcat名字相匹配
    ip1
    Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat12"/>
    ip2
    Engine name="Standalone" defaultHost="localhost" jvmRoute="tomcat13"/>
    好了,apache和tomcat的配置好了,可以访问了。

    这里,再提供一个链接,可以监控和配置负载均衡的各种信息
    http://192.168.1.11/jkstatus或http://my.linuxcoffee.org、jkstatus来访问网站。
    注:需要在web.xml的display-name后面 下加上一段。 这个跟顺序有关的,不然,xml文件会变红哦。
    <xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
    <display-name>TomcatDemodisplay-name>
    <distributable/>
    <web-app>


相关推荐

    Tomcat集群Cluster实现原理剖析.doc

    Tomcat集群Cluster实现原理剖析.doc

    tomcat Cluster

    Tomcat集群的实现主要依赖于Apache的JGroups库,它提供了网络通信和集群成员管理功能。在Tomcat的源码中,`org.apache.catalina.ha`和`org.apache.catalina.cluster`包下包含了与集群相关的类和接口。例如,`Backup...

    tomcat7集群

    通过集群,可以实现多个Tomcat实例协同工作,提高系统的处理能力和容错性。 【标签】:Tomcat7集群、负载均衡、session复制、高可用性 【正文】: 1. **复制服务器实例**:首先,你需要在不同的物理或虚拟机上...

    轻松配置linux Tomcat集群 PDF

    本篇内容将详细探讨如何在Linux环境中配置Tomcat集群,以提高系统的可用性和性能。 一、Linux基础 在开始配置之前,需要对Linux操作系统有一定的了解。熟悉基本的命令行操作,如文件管理、用户权限、网络设置等,这...

    关于tomcat集群部署总结

    基于上述理论,我们来具体分析如何在Tomcat集群中配置Session管理策略。 1. **Session复制配置**: - 在`conf/catalina.xml`文件中,找到`&lt;Cluster&gt;`标签,并取消对`&lt;Manager&gt;`元素的注释,启用Session复制功能。...

    Java企业级电商项目架构演进之路 Tomcat集群与Redis分布式-课程章节1

    【Java企业级电商项目架构演进之路 Tomcat集群与Redis分布式】 这门课程是针对Java开发者设计的,旨在提升他们的企业级项目架构能力,特别是聚焦于Tomcat集群和Redis分布式缓存的应用。课程内容丰富,适合希望晋升...

    Tomcat集群——使用MSM管理集群Session

    本篇将深入探讨如何使用Multicast Session Manager (MSM)来实现在Tomcat集群中的Session共享。 【描述】:由于描述为空,我们直接进入主题。在Tomcat集群中,当用户请求被负载均衡到不同的服务器时,保持用户的...

    Tomcat集群与负载均衡

    本文将深入探讨Tomcat集群与负载均衡的概念、原理及其实现方式,旨在帮助读者理解如何构建高可用、高并发的Web应用环境。 #### 二、Tomcat集群与负载均衡的核心概念 **1. 集群(Cluster)** 集群是指一组通过网络...

    一晚上搞定Tomcat集群

    4. **集群通信**:Tomcat集群中的节点间需要通信,这通常通过`JVMRoute`和`Cluster`配置实现。`JVMRoute`是每个节点的唯一标识,`Cluster`配置则定义了节点间的通信协议和策略。 5. **负载均衡**:你可以使用内置的...

    nginx+ tomcat + redis-cluster 实现session同步所需的jar包

    这里我们将深入探讨如何使用Nginx、Tomcat和Redis-Cluster来实现Session同步,以及涉及到的jar包的作用。 首先,让我们了解每个组件的角色: 1. **Nginx**:通常作为反向代理和负载均衡器,它接收来自客户端的请求...

    Apache + Tomcat集群配置详解

    - `&lt;Cluster&gt;`配置中的`SimpleTcpCluster`确保了在Tomcat集群中的所有节点之间同步会话数据。这意味着用户在集群中的任何一台服务器上的操作都可以在其他服务器上继续,增强了用户体验的连续性。 4. **应用配置**...

    tomcat cluster参考资料3

    【标题】:“Tomcat集群(Cluster)参考资料3” 在Java Web开发中,Apache Tomcat作为一款广泛应用的开源Servlet容器,其集群(Cluster)功能对于处理高并发、提供高可用性和负载均衡至关重要。Tomcat Cluster是...

    apache+tomcat集群配置文件和文档

    这份"apache+tomcat集群配置文件和文档"将涵盖以上所有要点,指导你逐步配置和测试Apache+Tomcat集群。按照文档操作,你将能够构建出一个高效且稳定的Web服务环境。在实际操作中,务必根据你的硬件资源和具体需求...

    Apache和Tomcat集群测试案例

    在IT行业中,Apache和Tomcat是...通过深入研究这些文件,我们可以更好地理解和实践Apache和Tomcat集群的搭建与优化。在实际操作过程中,一定要遵循最佳实践,并根据自己的具体需求调整配置,以达到理想的性能和可靠性。

    nginx 和Tomcat 集群

    6. **Tomcat集群配置**:在Tomcat端,需要配置集群以共享session信息,确保用户在不同节点之间切换时,其会话状态能够保持一致。 7. **日志管理**:Nginx可以集中处理所有请求的日志,便于监控和分析系统运行情况。...

    tomcat架构原理剖析

    10. **Cluster(集群)**:Tomcat支持集群,可以将多台Tomcat服务器组织成一个集群,以实现负载均衡和高可用性。当一台服务器故障时,请求可以自动路由到其他正常运行的服务器。 了解以上这些核心组件及其交互,有...

    Liunx 下 nginx+tomcat 集群建设

    在Linux环境中,构建一个nginx与tomcat...总结来说,构建Linux下的nginx+tomcat集群是一项涉及到网络架构、服务器配置、负载均衡策略等多个方面的技术任务。通过合理的配置和管理,可以大大提高Web应用的稳定性和效率。

    Tomcat集群

    总的来说,Tomcat集群是一项复杂的工程,需要对Tomcat的内部工作原理、网络通信、负载均衡和分布式系统有深入理解。不过,一旦正确配置,它能显著提升服务的可用性和性能,为大型Java Web应用提供强大的支持。在实际...

    tomcat集群配置

    【Tomcat集群配置】 在高流量的Web应用中,单个服务器可能无法处理所有请求,这时就需要使用集群来分散负载,提高系统可用性和容错性。Tomcat作为流行的Java Servlet容器,支持集群配置,实现多台Tomcat服务器共享...

    Apache+Tomcat集群的负载均衡配置文件和测试文件

    本主题聚焦于"Apache+Tomcat集群的负载均衡配置",通过Apache作为前端代理服务器,对后端的多个Tomcat实例进行负载分发,以实现高可用和高性能的服务。 首先,我们要理解负载均衡的基本概念。负载均衡是指将流入的...

Global site tag (gtag.js) - Google Analytics