Session會話保持機制的原理與Tomcat Session共享的幾種實現方式(Session Cluster、memcached+MSM)

1、Session的定義

  在計算機科學中,特別是在網絡中,session是兩個或更多個通訊設備之間或計算機和用戶之間的臨時和交互式信息交換。session在某個時間點創建,而後在以後的某一時間點拆除。創建的通訊session能夠在每一個方向上涉及多個消息。session一般是有狀態的,這意味着至少一個通訊部分須要保存關於會話歷史的狀態信息以便可以進行通訊,而在無狀態通訊中,通訊由具備響應的獨立請求組成。——Wikipediacss

  Session:在計算機中,尤爲是在網絡應用中,稱爲「會話控制」。Session 對象存儲特定用戶會話所需的屬性及配置信息。這樣,當用戶在應用程序的 Web 頁之間跳轉時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。當用戶請求來自應用程序的 Web 頁時,若是該用戶尚未會話,則 Web 服務器將自動建立一個 Session 對象。當會話過時或被放棄後,服務器將終止該會話。Session 對象最多見的一個用法就是存儲用戶的首選項。例如,若是用戶指明不喜歡查看圖形,就能夠將該信息存儲在 Session 對象中。——百度html

2、Session的做用與意義

  在WEB應用中,通常都是採用http協議進行通訊,但http是一種無狀態的通訊協議,這裏的無狀態是指協議對於事務處理沒有記憶能力,在會話結束後,服務器不知道客戶端是什麼狀態。在http協議初期,爲了保證WEB的併發訪問處理能力,http協議不會保存客戶端訪問的任何狀態信息。後來http協議中加入了keep-alive功能,這是一種會話保持機制,這樣即可以將會話持續保持一段時間,當用戶在這個時間段又一次訪問時會提升響應速度節省資源,但keep-alive也不會記錄用戶的狀態,只是讓鏈接保持一段時間,當用戶超過這個時間段再次訪問,依然仍是會當作新請求進行處理。但在WEB應用中有不少場景都須要根據用戶的歷史訪問狀態來將請求分配給後端服務器處理,例如登陸記錄、購物車記錄,瀏覽記錄等,用戶每次訪問都沒法找到之前的記錄是很影響用戶體驗的,這樣就誕生了cookie和session機制。前端

  先來講說cookie,當用戶訪問www.abc.com時須要登陸,由於http是無狀態的,因此致使訪問www.abc.com/xxx又須要從新登陸,這樣是很頭痛的事情,cookie的出現解決了這個問題,cookie能夠將用戶的少許信息保存至用戶客戶端本地,它將www.abc.com域名做爲一個全局,在用戶登陸此域名下的全部URI時都不須要從新登錄。但用戶本地的存儲大小是有限的,而且將一些私密信息儲存在本地是有安全風險的。java

  如何保證用戶體驗,又能保證安全性,這就是Session的意義,session也是一種用戶狀態儲存機制,但與cookie不一樣的是,session儲存在後端服務器的內存中。session在web應用中有着很是重要的意義,它能夠很方便很安全的控制訪問權限。linux

2、常見的Session會話保持方式

1.Session sticky(session會話粘性)

會話粘性是指在用戶第一次訪問後按必定的算法與之將其中一臺後端服務器作綁定,通常分爲兩種:nginx

a.souce_ip:如nginx中的ip_hash算法、LVS中的sh算法web

b.cookie:HAProxy中的cookie算法

2.Session Cluster(session集羣)

  Session Cluster是指將後端服務器組成一個集羣,共享全部的session, 當某一臺服務器故障後不至於影響用戶體驗。這種方法通常用在後端服務器較少的狀況(3-4臺),由於當服務器太多時會佔用大量的IO,影響集羣性能。數據庫

下面將以Tomcat爲例介紹介紹這種session保持機制。apache

1.實現基礎

Tomcat Session Cluster的實現是利用組播將集羣中的session進行共享,這與keepalived相似。Tomcat原生就支持這種機制,因此配置起來比較簡單,但不能支持太多的主機,

2.結構與IP分配

Nginx主機:IP:192.168.29.109

Tomcat主機集羣:192.168.29.10七、192.168.29.13二、192.168.29.110

安裝好Nginx和Tomcat,教程:http://www.javashuo.com/article/p-qbvvzhgh-bk.html

關閉防火牆和Selinux

 1.配置Nginx

vim /etc/nginx/nginx.conf #配置主配置文件
upstream tcsv { #在http模塊中插入upstream模塊
    server 10.10.10.130:8080;
    server 10.10.10.131:8080;
    server 10.10.10.132:8080;
                }
vim /etc/nginx/conf.d/tomcat.conf #添加虛擬主機
server {
        listen 80;
        server_name www.ready.com;
        location  / {
                proxy_pass http://tcsv;
                }
        }

2.配置Tomcat,建立.jsp測試頁

mkdir -pv /var/lib/tomcat/webapps/test/{WEB-INF,META-INF,classes,lib} #建立jsp文件所需目錄
vim /var/lib/tomcat/webapps/test/index.jsp #建立jsp測試文件,功能爲session ID監控
<%@ page language="java" %>
<html>
    <head><title>TomcatA</title></head>
    <body>
        <h1><font color="red">Tomcat.ready.com</font></h1> #將3臺Tomcat主機配置爲不一樣顏色,我這裏分別是red、green、blue
        <table align="centre" border="1">
        <tr>
            <td>Session ID</td>
        <% session.setAttribute("ready.com","ready.com"); %>
            <td><%= session.getId() %></td>
        </tr>
            <tr>
                <td>Created on</td>
                <td><%= session.getCreationTime() %></td>
            </tr>
        </table>
    </body>
</html>

3.啓動Nginx和Tomcat,並刷新頁面(修改hosts添加本地解析)

不一樣顏色表明不一樣主機的響應,咱們能夠發現就算響應的主機相同Session ID也不一樣,這說明Session機制未開啓(由於前端Nginx調度默認採用的rr算法),就算在同一主機訪問也會被識別爲不一樣用戶。

 4.配置Tomcat Cluster服務

Tomcat原生就是支持此服務的,因此只須要在/etc/tomcat/server.xml中嵌入 <Cluster> 組件便可,要注意的是 <Cluster> 組件只能用在 <Engine> 和 <Host> 中。注意事項以下

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 和 MessageDispatch15Interceptor 

vi /etc/tomcat/server.xml
a.將下面的代碼插入 <Engine> 或者 <Host> 中
<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.29.132" #填寫本機IP地址,默認爲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>
b.將默認web.xml文件(/etc/tomcat/web.xml)複製到事先建立好的/usr/share/tomcat/webapps/test/WEB-INF/目錄下並修改

web.xml文件是用來初始化配置信息:好比Welcome頁面、servlet、servlet-mapping、filter、listener、啓動加載級別等。

cp /etc/tomcat/web.xml /usr/share/tomcat/webapps/test/WEB-INF/
vim /usr/share/tomcat/webapps/test/WEB-INF/web.xml

在 <web-app> 內任意位置插入代碼 <distributable/> ,其餘Tomcat主機也作相同操做。

c.重啓Tomcat服務,查看Tomcat狀態

在日誌中看到下面的信息就說明session共享配置成功:

d.刷新頁面,觀察session ID的變化

能夠看到無論怎麼刷新Session ID都保持不變,但標題顏色會變化,說明不管去前端Nginx怎麼調度Session都沒有發生變化。

e.注意事項

1.在插入 <Cluster> 組件時要注意 <Receiver> 中的 address= 的IP配置,儘可能不要用「auto」。

2.Tomcat主機的網關必定要設置正確,否則沒法發送和接收組播信息。

3.要在日誌中看到相似 [tcp://{192, 168, 29, 107}:4000,{192, 168, 29, 107},4000, alive=1037 的信息才說明組播信息成功發送,也可使用 tcpdump 命令來檢查組播信息狀態:

tcpdump -i ens33 -nn host 228.0.0.4

 3.Tomcat+memcached+msm實現Session共享

  在Tomcat Session Cluster方式實現session共享時,後端不能承載太多的Tomcat主機,只適用於小型的集羣使用,爲了克服這一問題,咱們能夠將後端的Tomcat集羣的全部session都存放在一個共享的存儲中,這樣無論用戶請求被反代到哪個後端服務器都不會影響體驗。

1.memcached簡介

  Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。memcached特性:

1.僅可用來存儲可序列化的數據。

2.分佈式緩存:互不通訊的分佈式集羣。

3.數據存儲在內存中,重啓即丟失數據。

4.緩存耗盡:LRU

5.惰性清理機制。

3.安裝memcached

  memcached已經收錄在yum的base倉庫,安裝起來很是簡單。

~]# yum install -y memcached

  查看memcached的配置文件

~]# cat /etc/sysconfig/memcached
PORT="11211" #監聽端口
USER="memcached" #用戶名
MAXCONN="1024" #最大併發鏈接數
CACHESIZE="64" #緩存空間大小,默認爲64MB
OPTIONS=""

  memcached經常使用選項:

memcached程序的經常使用選項:
-m <num>:Use <num> MB memory max to use for object storage; the default is 64 megabytes.
-c <num>:Use <num> max simultaneous connections; the default is 1024.
-u <username>:以指定的用戶身份來運行進程;
-l <ip_addr>:監聽的IP地址,默認爲本機全部地址;
-p <num>:監聽的TCP端口, the default is port 11211.
-U <num>:Listen on UDP port <num>, the default is port 11211, 0 is off.
-M:內存耗盡時,不執行LRU清理緩存,而是拒絕存入新的緩存項,直到有多餘的空間可用時爲止;
-f <factor>:增加因子;默認是1.25;
-t <threads>:啓動的用於響應用戶請求的線程數;

4.Memcached Session Manager(MSM)安裝

  MSM是一個將Tomcat Session存儲在memcached中的工具,這樣就能克服Tomcat自建的session共享機制後端服務器的數量限制。

試驗結構圖:

5.下載MSM所需.jar文件並放在Tomcat安裝目錄的lib目錄下

  我這裏是yum安裝的,目錄是在/usr/share/java/tomcat/下,須要複製到該目錄的文件以下(兩臺Tomcat主機操做相同),這一步很重要,若是文件版本不對會致使後面session共享不成功,我所用到的版本以下:

memcached-session-manager-1.8.2.jar
memcached-session-manager-tc7-1.8.2.jar
msm-javolution-serializer-1.8.2.jar
spymemcached-2.10.2.jar
javolution-5.5.1.jar

放在 /usr/share/java/tomcat/ 目錄下

6.在/etc/tomcat/server.xml默認配置內的<Host>上增長<Context>

在兩臺Tomcat主機上修改相同配置

vim /etc/tomcat/server.xml

<Host ......
<Context path="/test" docBase="test" reloadable="true"> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:192.168.29.107:11211,n2:192.168.29.110:11211" failoverNodes="n1" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory" /> </Context>
......
</Host>

7.建立java測試項目

192.168.29.107主機上的配置:

mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib}
vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<html>
  <head><title>TomcatB</title></head>
  <body>
    <h1><font color="blue">Tomcat.Ready.com</font></h1>
    <table align="centre" border="1">
      <tr>
        <td>Session ID</td>
    <% session.setAttribute("ready.com","ready.com"); %>
        <td><%= session.getId() %></td>
      </tr>
      <tr>
        <td>Created on</td>
        <td><%= session.getCreationTime() %></td>
     </tr>
    </table>
  </body>
</html>

192.168.29.110主機上的配置:

mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib}
vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<html>
  <head><title>TomcatB</title></head>
  <body>
    <h1><font color="red">Jerrmouse.Ready.com</font></h1>
    <table align="centre" border="1">
      <tr>
        <td>Session ID</td>
    <% session.setAttribute("ready.com","ready.com"); %>
        <td><%= session.getId() %></td>
      </tr>
      <tr>
        <td>Created on</td>
        <td><%= session.getCreationTime() %></td>
     </tr>
    </table>
  </body>
</html>

8.啓動Tomcat和memcached,並查看是否正常運行

systemctl start tomcat
systemctl start memcached
ss -lntup

完成上述步驟後瀏覽器訪問顯示以下:

Session ID後面多出了n1字符,而且不斷刷新頁面Session ID都不會改變,說明MSM+Tomcat的session共享配置成功。

再強調一次,複製到/usr/share/java/tomcat/的jar文件版本很重要。

相關文章
相關標籤/搜索