前言
对于高访问量、高并发量的网站或web应用来说,目前最常见的解决方案应该就是利用负载均衡进行server集群,例如比较流行的nginx+memcache+tomcat。集群之后比如我们有N个Tomcat,用户在访问我们的网站时有可能第一次请求分发到tomcat1下,而第二次请求又分发到了tomcat2下,有过web开发经验的朋友都知道这时session不一致会导致怎样的后果,所以我们需要解决一下多个tomcat之间session共享的问题。
准备一个最简单的web项目(在IDE中创建部署,拷贝出来即可),并修改index.jsp的内容如下:
-
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
-
<%
-
String path = request.getContextPath();
-
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
-
%>
-
-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
<html>
-
<head>
-
<base href="<%=basePath%>">
-
-
<title>My JSP 'index.jsp' starting page</title>
-
<meta http-equiv="pragma" content="no-cache">
-
<meta http-equiv="cache-control" content="no-cache">
-
<meta http-equiv="expires" content="0">
-
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
-
<meta http-equiv="description" content="This is my page">
-
<!--
-
<link rel="stylesheet" type="text/css" href="styles.css">
-
-->
-
</head>
-
-
<body>
-
-
SessionID:<%=session.getId()%>
-
<BR>
-
SessionIP:<%=request.getServerName()%>
-
<BR>
-
SessionPort:<%=request.getServerPort()%>
-
<%
-
out.println("This is Tomcat Server 11111");
-
%>
-
</body>
-
</html>
这样基本工作就做完了,下面需要修改tomcat的配置文件,我们打开conf下的server.xml文件,找到下面这一行:
-
<Engine name="Catalina" defaultHost="localhost">
不需要做任何修改,在这一行的下面加入如下代码:
-
<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官方文档中的cluster-howto.html中看到相关注意事项,其中有一条需要注意一下:
Make sure your web.xml has
the <distributable/> element
很明显是说我们的web项目的web.xml文件中需要有<distributable/>这个元素,所以在我们刚才引入的web项目中做如上的修改。

注意:此处的web.xml不是tomcat的web.xml而是项目的web.xml
这样我们的基本配置就完成了,因为是集群,所以在tomcat_cluster目录下拷贝一份tomcat1,并重命名成tomcat2。
tomcat2的server.xml修改有以下3点:
1.将<Server
port="8005" shutdown="SHUTDOWN" debug="0">的8005改为其它的端口
2.
将<Connector port="8080"
protocol="HTTP/1.1"
maxThreads="150" connectionTimeout="20000"
redirectPort="8443" /> 的8080改为其他端口
3.
将<Connector port="8009" enableLookups="false" redirectPort="8443" debug="0"
protocol="AJP/1.3" />的8009改为其它的端口。
OK,再访问一下我们的测试项目,看看session是否一致:

可以发现我们两个tomcat下的这两个项目Session完全一致,刷新也不会变,到此为止我们就算成功实现了Session共享,也就是说我们tomcat已经成功完成了任务,剩余的交给nginx就OK了。