1. 程式人生 > >多個Tomcat之間實現Session共享

多個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?
  1. <%@ page language="java"import="java.util.*"pageEncoding="UTF-8"%>
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>
  6. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  7. <html>
  8.   <head>
  9.     <basehref="<%=basePath%>">
  10.     <title>My JSP 'index.jsp' starting page</title>
  11.     <metahttp-equiv="pragma"content="no-cache">
  12.     <metahttp-equiv="cache-control"content="no-cache"
    >
  13.     <metahttp-equiv="expires"content="0">
  14.     <metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">
  15.     <metahttp-equiv="description"content="This is my page">
  16.     <!-- 
  17.     <link rel="stylesheet" type="text/css" href="styles.css"> 
  18.     -->
  19.   </head>
  20.   <body>
  21.         SessionID:<%=session.getId()%>
  22.         <BR>
  23.         SessionIP:<%=request.getServerName()%>
  24.         <BR>
  25.         SessionPort:<%=request.getServerPort()%>
  26.         <%  
  27.         out.println("This is Tomcat Server 11111");  
  28.         %>
  29.   </body>
  30. </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?
  1. <Enginename="Catalina"defaultHost="localhost">
<Engine name="Catalina" defaultHost="localhost">
不需要做任何修改,在這一行的下面加入如下程式碼: [html] view plain copy print?
  1. <ClusterclassName="org.apache.catalina.ha.tcp.SimpleTcpCluster"
  2.                 channelSendOptions="8">
  3.          <ManagerclassName="org.apache.catalina.ha.session.DeltaManager"
  4.                   expireSessionsOnShutdown="false"
  5.                   notifyListenersOnReplication="true"/>
  6.          <ChannelclassName="org.apache.catalina.tribes.group.GroupChannel">
  7.            <MembershipclassName="org.apache.catalina.tribes.membership.McastService"
  8.                        address="228.0.0.4"
  9.                        port="45564"
  10.                        frequency="500"
  11.                        dropTime="3000"/>
  12.            <ReceiverclassName="org.apache.catalina.tribes.transport.nio.NioReceiver"
  13.                      address="auto"
  14.                      port="4000"
  15.                      autoBind="100"
  16.                      selectorTimeout="5000"
  17.                      maxThreads="6"/>
  18.            <SenderclassName="org.apache.catalina.tribes.transport.ReplicationTransmitter">
  19.            <TransportclassName="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
  20.            </Sender>
  21.            <InterceptorclassName="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
  22.            <InterceptorclassName="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
  23.          </Channel>
  24.          <ValveclassName="org.apache.catalina.ha.tcp.ReplicationValve"
  25.                 filter=""/>
  26.          <ValveclassName="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
  27.          <DeployerclassName="org.apache.catalina.ha.deploy.FarmWarDeployer"
  28.                    tempDir="/tmp/war-temp/"
  29.                    deployDir="/tmp/war-deploy/"
  30.                    watchDir="/tmp/war-listen/"
  31.                    watchEnabled="false"/>
  32.          <ClusterListenerclassName="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
  33.          <ClusterListenerclassName="org.apache.catalina.ha.session.ClusterSessionListener"/>
  34.        </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。