zoukankan      html  css  js  c++  java
  • Tomcat7 Cluster 集群

    Tomcat7 自带的集群功能是通过session复制完成的,现有两个复制方式:

    • DeltaManager:

        将session复制到所有tomcat节点中,不管是否有相应的应用(it will replicate to all nodes, even nodes that don't have the application deployed.)。缺点是如果集群节点很多,此种方式的系统消耗太大。具体节点多少算多,官方没有给出数量级。

    • BackupManager:

        将session复制到一个备份节点中,并且只复制到有相应应用的节点。(This manager only replicates the session data to one backup node, and only to nodes that have the application deployed.)缺点是这种方式没有像DeltaManager一样经过大规模的应用测试。

    一个简单的Tomcat集群结构

                  DNS Round Robin

                              |

                     Load Balancer 

                     /                      

            Cluster1               Cluster2

             /                           /            

    Tomcat1  Tomcat2  Tomcat3  Tomcat4

    Tomcat7中运行session复制,需要完成以下步骤(先有个印象,再看下面的实例):

    • session中所有的属性(attributes)必须实现java.io.Serializable
    • 去掉配置文件server.xml中cluster元素的注释
    • 如果要自定义cluster valves,确认在Cluster元素里定义ReplicationValve。
    • 如果Tomcat节点运行在同一台服务器上,确保tcpListenPort属性值唯一。在大多数情况下,Tomcat可以自动检测4000-4100范围内的端口
    • 确保应用中web.xml文件有<distributable/>元素
    • 如果使用mod_jk,确保设置jvmRoute属性<Engine name="Catalina" jvmRoute="node01">,并且这个属性要和workers.properties相同
    • 确保所有节点都有相同的时间。
    • 确保loadbalancer被设置为粘性session模式(sticky session)

    注意:浏览器会在某些情况下创建新的Session。

    配置:

    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
             channelSendOptions="8">
        <!--
        <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="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|.*.jpeg|.*.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>
    
    下面详细说明一下:
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
             channelSendOptions="6">
    

      

    Cluster元素可以是<Engine>或者<Host>的子元素,如果使用farm war deploy功能,则必须是<Host>的子元素。SimpleTcpCluster是官方提供的唯一一个Cluster。channaelSendOptions是设置SimpleTcpCluster.send方法发送消息的方式,默认值是8。参考:http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/tribes/Channel.html
    <!--
    <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"/>
    默认的manager。在Tomcat5.x以后每个webapp都可以配自己的manager,但是每个节点上相同的webapp要配置相同的manager。如果<Context>中没有manager的配置则使用上面的配置。更多信息参考:http://tomcat.apache.org/tomcat-7.0-doc/config/cluster-manager.html
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
    Channel元素是Tribes,该元素封装所有沟通和成员逻辑。更多信息参考:http://tomcat.apache.org/tomcat-7.0-doc/config/cluster-channel.html
    <Membership className="org.apache.catalina.tribes.membership.McastService"
                address="228.0.0.4"
                port="45564"
                frequency="500"
                dropTime="3000"/>
    通过组播方式建立成员,通过address和port设置一个组播,在相同组播下为同一个集群。Tribes也支持静态成员,通过使用StaticMembershipInterceptor。更多信息参考:http://tomcat.apache.org/tomcat-7.0-doc/config/cluster-membership.html
    <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
              address="auto"
              port="5000"
              selectorTimeout="100"
              maxThreads="6"/>
    在Tribes中,发送(sender)和接收(receiver)是分开的两个组件。每个节点的address和port是不同的(如果节点有不同的IP地址,可以使用"auto",如果节点在同一个IP上,则port必须不同)。这个组件中有一个线程池,可以配置相关信息。更多信息参考:http://tomcat.apache.org/tomcat-7.0-doc/config/cluster-receiver.html
    <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
        <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
    </Sender>
    发送(sender)组件,这个就这么配,没什么贴别特别说明的。更多信息参考:http://tomcat.apache.org/tomcat-7.0-doc/config/cluster-sender.html
        <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>
    Tribes用堆栈发送信息,在堆栈中的每个元素都要通过interceptor。
    TcpFailureDetector - 通过TCP验证成员是否正常。
    MessageDispatch15Interceptor - 调度消息到线程(线程池),异步发送消息。
    ThroughputInterceptor - 打印出消息流量的简单统计
    注意interceptor的配置顺序。
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
           filter=".*.gif|.*.js|.*.jpeg|.*.jpg|.*.png|.*.htm|.*.html|.*.css|.*.txt"/>
    过滤一些不会修改session的request。更多信息参考:http://tomcat.apache.org/tomcat-7.0-doc/config/cluster-valve.html
    Xml代码  收藏代码
    1. <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"  
    2.           tempDir="/tmp/war-temp/"  
    3.           deployDir="/tmp/war-deploy/"  
    4.           watchDir="/tmp/war-listen/"  
    5.           watchEnabled="false"/>  
    默认的tomcat集群支持Farm部署,通过一个节点,可以部署和卸载应用到其他节点。集群中只设置一个主节点,将watchEnabled设为true,主节点将监听watchDir的变化,先更新本节点的deployDir,之后更新其他节点的deployDir。集群中其他节点的watchEnabled设为false。如果要执行此功能,Cluster必须是Host的子元素。
    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
              tempDir="/tmp/war-temp/"
              deployDir="/tmp/war-deploy/"
              watchDir="/tmp/war-listen/"
              watchEnabled="false"/>
    当使用DeltaManager时,通过ClusterSessionListener接收和传播信息。
     
    三、测试
    到现在为止我们配置了一个Tomcat,复制这个Tomcat,修改应该修改的部分(如果是同一台机器则需要修改一些端口和jvmRoute,如果不是同一台机器只需修改jvmRoute)。
    之后建立一个简单的webapp,记得web.xml中添加<distributable/>元素。如下:
        ......    
        <description>
          Servlet and JSP Examples.
        </description>
        <display-name>Servlet and JSP Examples</display-name>
    
        <distributable/>
    
        <!-- Define example filters -->
        <filter>
            <filter-name>Timing filter</filter-name>
            <filter-class>filters.ExampleFilter</filter-class>
            <init-param>
                <param-name>attribute</param-name>
                <param-value>filters.ExampleFilter</param-value>
            </init-param>
        </filter>
        ......
    

      

    在项目中添加一个广泛使用的测试jsp:
    <%@ page contentType="text/html; charset=UTF-8" %>  
    <%@ page import="java.util.*" %>  
    <html><head><title>Cluster Test</title></head>  
    <body>  
    <%  
      //HttpSession session = request.getSession(true);  
      System.out.println(session.getId());  
      out.println("<br> SESSION ID:" + session.getId()+"<br>");    
      // 如果有新的请求,则添加session属性  
      String name = request.getParameter("name");  
      if (name != null && name.length() > 0) {  
         String value = request.getParameter("value");  
         session.setAttribute(name, value);  
      }    
        out.print("<b>Session List:</b>");    
        Enumeration<String> names = session.getAttributeNames();  
        while (names.hasMoreElements()) {  
            String sname = names.nextElement();   
            String value = session.getAttribute(sname).toString();  
            out.println( sname + " = " + value+"<br>");  
            System.out.println( sname + " = " + value);  
       }  
    %>  
      <form action="testCluster.jsp" method="post">  
        名称:<input type=text size=20 name="name">  
         <br>  
        值:<input type=text size=20 name="value">  
         <br>  
        <input type=submit value="提交">  
       </form>  
    </body>  
    </html>  
    启动两个Tomcat,用浏览器访问一个Tomcat,设置一些属性到Session中,用相同浏览器代开另一个窗口,访问另一个Tomcat,看到页面中的Session含有之前设置的属性就说明Session复制成功。
    访问两个tomcat 发现sessionId相同 说明session复制成功!
     
     
    参考:http://toplchx.iteye.com/blog/1924322
  • 相关阅读:
    mysql跟踪提交的SQL语句
    Xamarin.Forms 启动App时获取屏幕宽高
    vs for mac xamarin.forms 将pcl转换为netstandard后报错
    MAC显示文件夹路径
    MAC下使用Charles抓取安卓模拟器数据
    mysql不能插入中文
    Xamarin的不归路-使用Gorilla Player实时预览XAML
    sqlserver2008附加数据库时提示“无法为该请求检索数据。 (Microsoft.SqlServer.Management.Sdk.Sfc)”
    Xamarin的不归路-ios模拟器调整窗口大小
    Xamarin的不归路-ios模拟器没有键盘
  • 原文地址:https://www.cnblogs.com/yixiwenwen/p/3578951.html
Copyright © 2011-2022 走看看