Session共享(Tomcat集羣實現和Redis緩存實現)

Session是啥?

Session 是另一種記錄客戶狀態的機制,不同的是 Cookie 保存在客戶端瀏覽器中,而 Session 保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上。這就是 Session。客戶端瀏覽器再次訪問時只需要從該 Session 中查找該客戶的狀態就可以了。

用瀏覽器打開一個網頁,用到的是HTTP協議,學過計算機的應該都知道這個協議,它是無狀態的,什麼是無狀態呢?就是說這一次請求和上一次請求是沒有任何關係的,互不認識的,沒有關聯的。但是這種無狀態的的好處是快速。

1. Session共享

正常情況下,HTTPSession是通過Servlet容器創建並進行管理的,創建成功之後都是保存在內存中。如果對項目進行橫向擴展搭建集羣,此時可以利用一些硬件和軟件工具來做負載均衡,此時,來自同一用戶的HTTP請求就有可能被分發到不同的實例上去,如何保證各個實例之間的Session的同步就成爲一個問題。

實現Session共享的方式主要有以下兩種:

  • Session複製共享
  • 基於緩存數據庫的session共享(基於memcache/redis緩存的session共享)

1.1 session複製共享:session replication

tomcat自帶session共享,主要是指集羣環境下,多臺應用服務器之間同步session,使session保持一致,對外透明。 如果其中一臺服務器發生故障,根據負載均衡的原理,調度器會遍歷尋找可用節點,分發請求,由於session已同步,故能保證用戶的session信息不會丟失,會話複製。

此方案的不足之處:

  • 必須在同一種中間件之間完成(如:tomcat-tomcat之間);
  • Session複製帶來的性能損失會快速增加.特別是當session中保存了較大的對象,而且對象變化較快時, 性能下降更加顯著,會消耗系統性能。這種特性使得web應用的水平擴展受到了限制;
  • Session內容通過廣播同步給成員,會造成網絡流量瓶頸,即便是內網瓶頸。

1.2 基於緩存數據庫的session共享(基於memcache/redis緩存的session共享)

使用緩存數據庫存取session信息,應用服務器接受新請求將session信息保存在緩存數據庫中,當應用服務器發生故障時,調度器會遍歷尋找可用節點,分發請求,當應用服務器發現session不在本機內存時,則去緩存數據庫中查找,如果找到則複製到本機,這樣實現session共享和高可用。

2. 多個Tomcat之間實現Session複製共享

<Engine defaultHost="localhost" name="Catalina">
<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自帶的集羣配置了,但是還需要修改應用的web.xml文件,加入標籤 <distributable/>,如下所示:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <distributable/>

</web-app>

:直接加在</web-app> 之前就可以了這個是加入tomcat的session 複製的,做tomcat集羣必須需要這一步,否則用戶的session 就無法正常使用。

3. Redis實現Session共享

3.1 spring-session + Redis實現Session共享

  1. 添加依賴
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
  1. web.xml中添加session過濾器
<!--session過濾器 放在過濾器頭--> 
<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.2 Spring Boot + Redis實現Session共享

SpringBoot提供了自動化的Session共享配置,它結合Redis可以非常方便的解決Session共享問題。使用Redis解決Session共享問題的原理很簡單,就是把原本存儲在不同服務器上的Session拿出來放在一個獨立的服務器上。步驟如下:

  1. 除了Redis的依賴之外,還要提供spring-session-data-redis依賴,Spring Session可以做到透明的替換掉應用的Session容器。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
  1. 編寫實現方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章