本文主要介紹在 Tomcat 集群中如何進行 Session 複製,文中所使用到的軟體版本:Centos 7.9.2009、Java 1.8.0_321、Tomcat 8.5.87。 1、快速配置 取消 conf/server.xml 文件中的以下註釋來啟用集群: <Cluster classNam ...
本文主要介紹在 Tomcat 集群中如何進行 Session 複製,文中所使用到的軟體版本:Centos 7.9.2009、Java 1.8.0_321、Tomcat 8.5.87。
1、快速配置
取消 conf/server.xml 文件中的以下註釋來啟用集群:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
使用上述配置將啟用 all-to-all 會話複製,它使用 DeltaManager 進行會話增量複製。all-to-all 意味著每個會話都將被覆制到群集中的所有其他節點。這對於較小的集群非常有效,但不建議在大型集群(超過4個節點左右)中使用它。此外,當使用 DeltaManage r時,Tomcat 將會話複製到所有節點,甚至是沒有部署該應用程式的節點。
為瞭解決這些問題,您將需要使用 BackupManager。BackupManager 僅將會話數據複製到一個備份節點,並且僅複製到已部署該應用程式的節點。一旦您使用 DeltaManage r運行了一個簡單的集群,您可能希望隨著增加集群中節點的數量而遷移到 BackupManager。
上述配置對應的詳細預設配置如下:
<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.MessageDispatchInterceptor"/> </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.ClusterSessionListener"/> </Cluster>
以下是一些重要的預設值:
1、組播地址為 228.0.0.4
2、組播埠為 45564(埠和地址一起確定集群成員身份)
3、廣播的 IP 是 java.net.InetAddress.getLocalHost().getHostAddress()(確保不要廣播127.0.0.1,這是一個常見錯誤)
4、用於監聽複製消息的 TCP 埠是在 4000-4100 範圍內第一個可用的伺服器套接字
5、偵聽器配置為 ClusterSessionListener
6、配置了兩個攔截器 TcpFailureDetector 和 MessageDispatchInterceptor
2、Session 複製實現步驟
1、所有會話屬性必須實現 java.io.Serializable 介面。
2、在 conf/server.xml 文件中取消註釋 Cluster 元素。
3、如果您定義了自定義集群閥門,請確保在 conf/server.xml 文件的 Cluster 元素下也定義了 ReplicationValve。
4、如果 Tomcat 實例在同一臺機器上運行,確保每個實例的 Receiver.port 屬性是唯一的。在大多數情況下,Tomcat 可以通過自動檢測 4000-4100 範圍內可用埠來解決此問題。
5、確保應用的 web.xml 具有 <distributable/> 元素。
6、如果使用 mod_jk,請確保在 Engine(<Engine name="Catalina" jvmRoute="node01">) 中設置 jvmRoute 屬性,並且 jvmRoute 屬性值與 workers.properties 中的 worker 名稱匹配。
7、確保所有節點具有相同的時間並與 NTP 服務同步.
8、確保負載均衡器配置為粘性會話模式。
3、實際操作
3.1、規劃
IP | 埠 | 用途 |
10.49.196.10 | 8080 | Tomcat1 |
10.49.196.11 | 8080 | Tomcat2 |
10.49.196.13 | 8080 | 反向代理(Nginx) |
3.2、修改 server.xml
取消 Tomcat 中 conf/server.xml 文件的以下註釋:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
3.3、添加 <distributable/>
這裡直接使用 Tomcat 自帶的應用 ROOT 做測試,在 webapps/ROOT/WEB-INF/web.xml 文件中增加 <distributable/>:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> <distributable/> </web-app>
3.4、添加測試頁面
新增 webapps/ROOT/index2.jsp 文件:
<body> SessionID:<%=session.getId()%> <br> SessionIP:<%=request.getLocalAddr()%> <br> SessionPort:<%=request.getLocalPort()%> </body>
3.5、配置反向代理
Nginx 的配置如下:
upstream tomcat { server 10.49.196.30:8080; server 10.49.196.31:8080; } server { listen 7070; server_name localhost; location / { proxy_pass http://tomcat; } }
3.6、測試
啟動兩個 Tomcat 及 Nginx,訪問代理頁面:
多次訪問代理頁面,可以看到 IP 不停的變化,但 SessionID 不變,說明 Session 複製有效。
參考:https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html。