多個Tomcat之間實現Session共享
前言
對於高訪問量、高併發量的網站或web應用來說,目前最常見的解決方案應該就是利用負載均衡進行server叢集,例如比較流行的nginx+memcache+tomcat。叢集之後比如我們有N個Tomcat,使用者在訪問我們的網站時有可能第一次請求分發到tomcat1下,而第二次請求又分發到了tomcat2下,有過web開發經驗的朋友都知道這時session不一致會導致怎樣的後果,所以我們需要解決一下多個tomcat之間session共享的問題。
環境準備
首先我們需要下載tomcat,這裡我們選擇tomcat7的解壓縮版:
下載完成後我們新建一個目錄叫tomcat_cluster(tomcat叢集的意思),直接解壓下載好的tomcat,並重命名為tomcat1,可以看到目錄結構如下:
準備一個最簡單的web專案(在IDE中建立部署,拷貝出來即可),並修改index.jsp的內容如下:
[html] view plain copy print?- <%@ 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>
- <basehref="<%=basePath%>">
- <title>My JSP 'index.jsp' starting page</title>
- <metahttp-equiv="pragma"content="no-cache">
- <metahttp-equiv="cache-control"content="no-cache"
- <metahttp-equiv="expires"content="0">
- <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">
- <metahttp-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>
<%@ 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檔案,找到下面這一行: [html] view plain copy print?
- <Enginename="Catalina"defaultHost="localhost">
<Engine name="Catalina" defaultHost="localhost">
不需要做任何修改,在這一行的下面加入如下程式碼:
[html]
view plain
copy
print?
- <ClusterclassName="org.apache.catalina.ha.tcp.SimpleTcpCluster"
- channelSendOptions="8">
- <ManagerclassName="org.apache.catalina.ha.session.DeltaManager"
- expireSessionsOnShutdown="false"
- notifyListenersOnReplication="true"/>
- <ChannelclassName="org.apache.catalina.tribes.group.GroupChannel">
- <MembershipclassName="org.apache.catalina.tribes.membership.McastService"
- address="228.0.0.4"
- port="45564"
- frequency="500"
- dropTime="3000"/>
- <ReceiverclassName="org.apache.catalina.tribes.transport.nio.NioReceiver"
- address="auto"
- port="4000"
- autoBind="100"
- selectorTimeout="5000"
- maxThreads="6"/>
- <SenderclassName="org.apache.catalina.tribes.transport.ReplicationTransmitter">
- <TransportclassName="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
- </Sender>
- <InterceptorclassName="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
- <InterceptorclassName="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
- </Channel>
- <ValveclassName="org.apache.catalina.ha.tcp.ReplicationValve"
- filter=""/>
- <ValveclassName="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
- <DeployerclassName="org.apache.catalina.ha.deploy.FarmWarDeployer"
- tempDir="/tmp/war-temp/"
- deployDir="/tmp/war-deploy/"
- watchDir="/tmp/war-listen/"
- watchEnabled="false"/>
- <ClusterListenerclassName="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
- <ClusterListenerclassName="org.apache.catalina.ha.session.ClusterSessionListener"/>
- </Cluster>
<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專案中做如上的修改。
這樣我們的基本配置就完成了,因為是叢集,所以在tomcat_cluster目錄下拷貝一份tomcat1,並重命名成tomcat2。
注意一下需要修改的地方:
1、首先肯定是埠號,所有port字樣的配置都修改一下保證兩個不重複,我這裡將tomcat1的埠修改為7080,tomcat2的埠修改為9080。
2、修改webapps下的專案中的index.jsp檔案,因為要測試session共享所以有必要區分一下,在jsp中加入一行靜態文字即可,我這裡是用“This is Tomcat Server 111111”和“This is Tomcat Server 22222”來進行區分的,下面分別啟動兩個tomcat進行測試,我們分別執行bin目錄下的startup.bat,發現第一個tomcat啟動之後,第二個無法啟動,這是因為啟動指令碼(startup.bat)沒有修改,引用同樣的CATALINA_HOME必然會報錯,所以請注意下面的第三點。
3、為我們的這兩個tomcat新增兩個環境變數——CATALINA_HOME2、CATALINA_HOME3分別指向這兩個tomcat的安裝目錄:
然後分別修改兩個tomcat中bin目錄下的兩個指令碼:startup.bat和catalina.bat,把tomcat1中的這兩個檔案中的%CATALINA_HOME%替換為%CATALINA_HOME2%,把tomcat2中的這兩個檔案中的%CATALINA_HOME%替換為%CATALINA_HOME3%,現在再啟動tomcat,會發現兩個tomcat都可以正常啟動了,解壓版的tomcat需要這樣配置一下。在瀏覽器中檢測一下tomcat是否可以成功訪問:
OK,再訪問一下我們的測試專案,看看session是否一致:
可以發現我們兩個tomcat下的這兩個專案Session完全一致,重新整理也不會變,到此為止我們就算成功實現了Session共享,也就是說我們tomcat已經成功完成了任務,剩餘的交給nginx就OK了。最後再強調一下,這兩個testdemo的web.xml中需要加這麼元素:
總結
本篇blog介紹了tomcat叢集之前的必備工作——session共享的配置,以及同時啟動兩個tomcat解壓縮版需要注意的問題,希望對看到的同學有所幫助吧,The End。