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