tomcat session共享(网上转载)

          强大的订票网站12306.cn给了我们一个教训,如果不想自己做的网站遇到用户多的情况就频繁崩溃,除了要好好的设计自己网站之外,还应该考虑点架构的问题了,所以先看下负载均衡的内容。

         负载均衡,想想其实很简单,就是一个tomcat忙不过来了,就让多个tomcat来做,可是请求来了到底应该用哪个tomcat来处理呢,这时候需要一个分发任务的tomcat,所以我们引入了apache 服务器。

我们引入的apache应该要有如下功能:

       1.能够分发请求到N个tomcat中

       2.能够尽量让每个tomcat工作量基本平均

       3.某个tomcat离开了,apache就不要请求分给他了,而是分给其它人。

 

       对于TOMCAT呢,除了正常功能外,需要哪些额外的功能呢?

       1.客户端应该不能感觉到请求分到不同tomcat时的差异

 

         废话就写这么多,希望给不理解负载均衡的人一些提示吧。

 

        接下来做个简单的例子,从最熟悉的tomcat说起,我们把这个系统分成几部分:

        一、tomcat session共享

        二、apache 请求分发

//TODO

 

      Tomcat session共享

       tomcat 官方文档中有这方面的介绍,我们下载tomcat目录下/webapps/docs就有html 格式的文档。如果没有怎么办,很简单下个有的吧。

       cluster-howto.html这个文件有很详细的解释了,考虑到是E文,我就做简单的解释吧,不过我E文也很烂,翻译基本靠“有道”,你懂的。

 

       实现session共享你有两个文件需要修改,考虑到不同版本的tomcat可能配置信息不一样,目前我试验的tomcat版本为:7.0.26

       1.修改catalina_home/conf/server.xml

       你应该能在配置文件里面发现这样的代码

Java代码   收藏代码
  1. <!-- You should set jvmRoute to support load-balancing via AJP ie :  
  2.    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">  
  3.    -->  

       你可以去掉注释然后再里面加入接下来的内容,可以不动他,完全拷贝如下配置信息到上续代码下面

 

 

Java代码   收藏代码
  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.                         <span style="background-color: #ffff00;">port="45564"</span>  
  12.                         frequency="500"  
  13.                         dropTime="3000"/>  
  14.             <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"  
  15.                       address="auto"  
  16.                       <span style="background-color: #ffff00;">port="4000"</span>  
  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>  

 如果在一台机器上测试,端口需要保证唯一,我把可能需要改的都用黄色警示下,除了修改新加入的部分,还要修改默认的配置,为了初学者方便我也给标出来,这里只给出要修改的

Java代码   收藏代码
  1. <Server port="8006" shutdown="SHUTDOWN">   
  2.   
  3. <!-- Define an AJP 1.3 Connector on port 8009 -->  
  4. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />  
  5.   
  6. <Connector port="8080" protocol="HTTP/1.1"  
  7.                connectionTimeout="20000"  
  8.                redirectPort="8443" />  

 

 

官网上有如下一段话

To run session replication in your Tomcat 7.0 container, the following steps should be completed:

  • All your session attributes must implement java.io.Serializable
  • Uncomment the Cluster element in server.xml
  • If you have defined custom cluster valves, make sure you have the ReplicationValve defined as well under the Cluster element in server.xml
  • If your Tomcat instances are running on the same machine, make sure the tcpListenPort attribute is unique for each instance, in most cases Tomcat is smart enough to resolve this on it's own by autodetecting available ports in the range 4000-4100
  • Make sure your web.xml has the <distributable/> element
  • If you are using mod_jk, make sure that jvmRoute attribute is set at your Engine<Engine name="Catalina" jvmRoute="node01" > and that the jvmRoute attribute value matches your worker name in workers.properties
  • 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.
  • 解释如下.
  • 所有session属性必须实现java.io.Serializable接口
  • 在server.xml中去掉"Cluster"元素的注释
  • 如果你定义了集群阀门(什么东西?),确定你在Cluster元素中有ReplicationValve定义
  • 如果你tomcat运行在同一台机器上,请确保端口唯一
  • 确定你web.xml 中有<distributable/>的元素(节点吧,不习惯元素这个说法)
  • 如果你使用mod_jk,设置 <Engine name="Catalina" jvmRoute="node01" >,
  • jvmRoute这个属性,并且保证唯一吧,因为接下来你负载均衡会用到。
  • 时间保持一致
  • 确保你的负载均衡配置了粘性会话模式

         好了,一个配置文件已经修改完了,剩下一个,项目的配置文件web.xml

        2、修改catalina_home/webapps/你的项目/WEB-INF/web.xml

       很简单,添加一行即可<distributable/>

 

添加一个测试的jsp到你的项目中去,testCluster.jsp,直接拷贝吧,我也是拷贝网上的

Xml代码   收藏代码
  1. <%@ page contentType="text/html; charset=GBK" %>    
  2. <%@ page import="java.util.*" %>    
  3. <html><head><title>Cluster Test</title></head>    
  4. <body>    
  5. <%    
  6.   //HttpSession session = request.getSession(true);    
  7.   System.out.println(session.getId());    
  8.   out.println("<br> SESSION ID:" + session.getId()+"<br>");      
  9.   // 如果有新的请求,则添加session属性    
  10.   String name = request.getParameter("name");    
  11.   if (name != null && name.length() > 0) {    
  12.      String value = request.getParameter("value");    
  13.      session.setAttribute(name, value);    
  14.   }      
  15.     out.print("<b>Session List:</b>");      
  16.     Enumeration<String> names = session.getAttributeNames();    
  17.     while (names.hasMoreElements()) {    
  18.         String sname = names.nextElement();     
  19.         String value = session.getAttribute(sname).toString();    
  20.         out.println( sname + " = " + value+"<br>");    
  21.         System.out.println( sname + " = " + value);    
  22.    }    
  23. %>    
  24.   <form action="testCluster.jsp" method="post">    
  25.     名称:<input type=text size=20 name="name">    
  26.      <br>    
  27.     值:<input type=text size=20 name="value">    
  28.      <br>    
  29.     <input type=submit value="提交">    
  30.    </form>    
  31. </body>    
  32. </html>    

 测试逻辑是这样的,访问tomcatA,提交一个键值对到session中,访问tomcatB,看是否看到这个键值对,修改也一样,图就不截了。

 

我的问题:

       在一台机器测试的时候两个tomcat,session可以同步,不在一台机器的时候session不能同步,据说跟"<Membership> 和 <Receiver>有关系,因为 membership是广播地址。。。。具体怎么解决还不知道,如果你知道麻烦提示下。
顺便说下,这种集群不要大于4台(官网也这么推荐的),否则网络带宽被大量的占用

 

 

 

猜你喜欢

转载自chengtong-java.iteye.com/blog/2174525