什么是會話保持
會話是指一個終端用戶與交互系統進行通訊的過程,比如從輸入賬戶密碼進入操作系統到退出操作系統就是一個會話過程。會話較多用于網絡上,TCP的三次握手就創建了一個會話,TCP關閉連接就是關閉會話。
Http協議是一種無狀態協議,所以需要使用Session機制來保存用戶的狀態,比如登錄狀態、常用信息等。
Session用于保存一次會話的相關信息,可以實現在多個頁面之間共享這些數據。
例如:你打開淘寶登錄了個人賬號,即使你瀏覽了再多的店鋪寶貝,切換了很多的頁面,用戶名是不變的,這個就是Session起的作用。直到你關閉瀏覽器,Session被銷毀,才會清除掉之前的登錄記錄。
今天和大家分享“Nginx+tomcat實現負載均衡的會話保持”就是實現:如果網站某個負載節點掛掉,請求被分配到新節點Session也會同步過來,實現會話保持,由此保證用戶無感知的瀏覽。
實現原理
使用Manager對象實現HTTP會話管理
DeltaManager作為會話管理器
用戶訪問nginx,nginx負載均衡到tomcat,用于Tomcat集群的會話管理器,將所有session會話的改變同步給集群中的每一個節點,實現會話復制。
實驗配置
Nginx配置
測試環境單臺服務器開了兩個tomcat,一臺對應8080端口,另一臺對應8090端口。
創建TomcatA TomcatB,分別配置tomcat server.xml
復制以下內容到 Engine下
添加此模塊:
- <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="192.168.224.145"
- port="4001"
- 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>
備注:
1.classname配置tomcat集群在進行信息傳遞時互相使用什么類來進行傳遞
channelsendoptions可以設置為2,4,8.10
2-確認發送 4-同步發送 8-異步發送
10-在異步模式下,可以通過加上確認發送(Acknowledge)來提高可靠性
2.manager決定如何管理集群的session信息
className-指定實現org.apache.catalina.ha.ClusterManager接口的類,用于信息之間的管理.
expireSessionsOnShutdown-設置為true時,一個節點關閉,將導致集群下的所有Session失效
notifyListenersOnReplication-集群下節點間的Session復制、刪除操作,是否通知session listeners
3.Channel是Tomcat節點之間進行通訊的工具。
Channel包括5個組件:Membership、Receiver、Sender、Transport、Interceptor
4.Membership維護集群的可用節點列表。用于檢測新增節點及掉線節點
address-組播地址(任意定義組播地址),如果需要阿里云ECS部署tomcat,因為ECS不支持組播,建議改用memcache或redis存儲session實現會話保持
port-組播端口 (兩個tomcat組播端口要一致)
frequency-發送心跳(向組播地址發送UDP數據包)的時間間隔(單位:ms)。默認值為500
dropTime-Membership在dropTime(單位:ms)內未收到某一節點的心跳,則將該節點從可用節點列表刪除。默認值為3000
5.Receiver : 接收器
address-接收消息的地址(默認auto,但是在虛擬機上開啟tomcat會報錯,建議配置本機IP地址)
port-接收消息的端口(如果在一臺服務器配置多個tomcat,需區分開端口)
autoBind-端口的變化區間
如果port為4000,autoBind為100,接收器將在4000-4099間取一個端口,進行監聽
selectorTimeout-NioReceiver 輪詢超時時間
maxThreads-線程池的***線程數
6.sender:發送器負責發送消息
- <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
- <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
- </Channel>
7.Valve :過濾器
8.Deployer:同步集群下的所有節點的一致性
9.ClusterListener : 監聽器,監聽Cluster組件接收的消息,使用DeltaManager時,Cluster接收的信息通過ClusterSessionListener傳遞給DeltaManager
配置web.xml
在web.xml中添加屬性,用于告訴web容器,該項目屬于分布式項目
添加標簽到web項目WEB-INF目錄
會話保持驗證
webapps/ROOT/index.jsp 創建測試頁面獲取sessionID
- tomcatA
- <%@ page language="java" %>
- <html>
- <head><title>TomcatA</title></head>
- <body>
- <h1><font color="red">TomcatA</font></h1>
- <table align="centre" border="1">
- <tr>
- <td>Session ID</td>
- <% session.setAttribute("TomcatA","TomcatA"); %>
- <td><%= session.getId() %></td>
- </tr>
- <tr>
- <td>Created on</td>
- <td><%= session.getCreationTime() %></td>
- </tr>
- </table>
- </body>
- </html>
- tomcatB
- <%@ page language="java" %>
- <html>
- <head><title>TomcatB</title></head>
- <body>
- <h1><font color="red">TomcatB</font></h1>
- <table align="centre" border="1">
- <tr>
- <td>Session ID</td>
- <% session.setAttribute("TomcatB","TomcatB"); %>
- <td><%= session.getId() %></td>
- </tr>
- <tr>
- <td>Created on</td>
- <td><%= session.getCreationTime() %></td>
- </tr>
- </table>
- </body>
- </html>
瀏覽器訪問驗證
總結:
tomcat實現會話保持有多種實現方式,這里只介紹了Manager對象實現,優點是利用tomcat自身集群session復制實現會話保持配置方便,缺點是像阿里云ECS這種不支持組播就無法用這種方式實現了。也可以使用memcache或redis存儲session會話,但這個要下載tomcat版本相對應的memcache jar包。