1. 程式人生 > >基於 spring-session 解決分散式 session 共享問題

基於 spring-session 解決分散式 session 共享問題

摘要:本文主要研究 基於 spring-seesion 解決分散式 session 的共享問題。首先講述 session 共享問題的產生背景以及常見的解決方案;然後講解本文主要研究的 spring-session 的概念和功能;接著演示了 spring-session 的兩種管理 sessionid 的實現方案,屬於實戰內容,需重點掌握;再接著對後臺儲存資料到 redis 上的資料結構進行了分析;然後對 spring-session 的核心原始碼進行了解讀,方便理解 spring-session 框架的實現原理;最後列舉了在使用 spring-session 的實踐過程中可能遇到的問題或坑,重點去理解一下。

直奔主題

HttpSession 是通過 Servlet 容器建立和管理的,像 Tomcat/Jetty 都是儲存在記憶體中的。而如果我們把 web 伺服器搭建成分散式的叢集,然後利用 LVS 或 Nginx 做負載均衡,那麼來自同一使用者的 Http 請求將有可能被分發到兩個不同的 web 站點中去。那麼問題就來了,如何保證不同的 web 站點能夠共享同一份 session 資料呢?

最簡單的想法將 session 管理從容器中獨立出來。而實現方案有很多種,下面簡單介紹下:

  • 第一種是使用容器擴充套件來實現,大家比較容易接受的是通過容器外掛來實現,比如基於 Tomcat 的 tomcat-redis-session-manager ,基於 Jetty 的 jetty-session-redis 等等。好處是對專案來說是透明的,無需改動程式碼。不過前者目前還不支援 Tomcat 8 ,或者說不太完善。但是由於過於依賴容器,一旦容器升級或者更換意味著又得從新來過。並且程式碼不在專案中,對開發者來說維護也是個問題。
  • 第二種是自己寫一套會話管理的工具類,包括 Session 管理和 Cookie 管理,在需要使用會話的時候都從自己的工具類中獲取,而工具類後端儲存可以放到 Redis 中。很顯然這個方案靈活性最大,但開發需要一些額外的時間。並且系統中存在兩套 Session 方案,很容易弄錯而導致取不到資料。
  • 第三種是使用框架的會話管理工具,也就是如下介紹的 spring-session ,可以理解是替換了 Servlet 那一套會話管理,接管建立和管理 Session 資料的工作。既不依賴容器,又不需要改動程式碼,並且是用了 spring-data-redis 那一套連線池,可以說是最完美的解決方案。

解決方案之 spring-session

介紹

Spring Session 提供了一套建立和管理 Servlet HttpSession 的完美方案。

功能

spring Session 提供了 API 和實現,用於管理使用者的 Session 資訊。除此之外,它還提供瞭如下特性:

  • 將 session 所儲存的狀態解除安裝到特定的外部 session 儲存彙總,如 Redis 中,他們能夠以獨立於應用伺服器的方式提供高質量的叢集。
  • 控制 sessionid 如何在客戶端和伺服器之間進行交換,這樣的話就能很容易地編寫 Restful API ,因為它可以從 HTTP 頭資訊中獲取 sessionid ,而不必再依賴於 cookie。
  • 在非 Web 請求的處理程式碼中,能夠訪問 session 資料,比如在 JMS 訊息的處理程式碼中。
  • 支援每個瀏覽器上使用多個 session,從而能夠很容易地構建更加豐富的終端使用者體驗。
  • 當用戶使用 WebSocket 傳送請求的時候,能夠保持 HttpSession 處於活躍狀態。

方案一由 cookie 管理 sessionid

在 maven 中新增如下依賴

<!-- spring-session-data-redis 是一個空的包,僅僅只有一個 META-INF 資料夾。它的作用就在於引入如下四個          
包 spring-data-redis,jedis,spring-session,commons-pool2
-->
  <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-data-redis</artifactId>
      <version>1.0.1.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.6.1.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.5.2</version>
  </dependency> 
  <dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session</artifactId>
    <version>1.1.0.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.2</version>
  </dependency>

在 spring 配置檔案中新增如下配置

<!-- redis 的 bean 配置如下 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"/>

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="127.0.0.1" />
    <property name="port" value="6379" />
    <property name="password" value="" />
    <property name="timeout" value="3600" />
    <property name="poolConfig" ref="jedisPoolConfig" />
    <property name="usePool" value="true" />
    <property name="database" value="0"/> <!-- 預設存放在0號庫中 -->
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>

<!-- 將 session 放入 redis, spring-session 會使用此 bean -->
<bean id="redisHttpSessionConfiguration"                     class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">                                                                    
    <property name="maxInactiveIntervalInSeconds" value="1800" />
</bean>

​這裡前面幾個 bean 都是操作 redis 時候使用的,最後一個 bean 才是 spring-session 需要用到的,其中的 id 可以不寫或者保持不變,這也是一個約定優先配置的體現。這個 bean 中又會自動產生多個 bean ,用於相關操作,極大的簡化了我們的配置項。其中有個比較重要的是 springSessionRepositoryFilter ,它將在下面的代理 filter 中被呼叫到。maxInactiveIntervalInSeconds 表示超時時間,預設是 1800 秒。上述配置可以採用 xml 來定義,官方文件中有采用註解來宣告一個配置類。

在 web.xml 中配置過濾器

  接下來在 web.xml 中新增一個 session 代理 filter ,通過這個 filter 來包裝 Servlet 的 getSession() 。需要注意的是這個 filter 需要放在所有 filter 鏈最前面,從而保證完全替換掉 tomcat 的 session。這個是約定。

<!-- delegatingFilterProxy -->
<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>

驗證

第一步:編寫 Controller 程式碼

@RequestMapping(value = "user", method = RequestMethod.POST)
public void setUser(HttpSession session) {
    User user = new User();
    user.setName("lyf");
    user.setPassword("123");
    session.setAttribute("user", user);
}
@RequestMapping(value = "user", method = RequestMethod.GET)
public String getUser(HttpSession session) {
    User user = (User) session.getAttribute("user");
    String name = user.getName();
    return "使用者名稱稱:" + name;
}

第二步:瀏覽器中訪問 Controller

  • post請求:localhost:8080/training/user

響應頭部如下:Response Headers:

Set-Cookie:SESSION=a2c10601-3204-454e-b545-85e84f587045; Path=/training/; HttpOnly
...

會發現瀏覽器 Cookie 中的 jsessionid 已經替換為 session**

此時使用 redis-cli 到 redis 庫中查詢如下:

springsession:0>keys *
1) spring:session:sessions:a2c10601-3204-454e-b545-85e84f587045
2) spring:session:expirations:1502595600000
  • get請求:localhost:8080/training/user

請求頭部如下:Request Headers:

Cookie:SESSION=a2c10601-3204-454e-b545-85e84f587045;

伺服器通過 Cookie 中的 session 識別碼從 redis 庫中找到了需要的 session 物件並返回,瀏覽器顯示如下:

使用者名稱稱:lyf
  • 總結

    通過如上 spring-session 配置即可將其整合到專案中,之後使用的所有有關 session 的操作,都會由 spring-session 來接管建立和資訊存取。官方預設 spring-session 中的 session 資訊都儲存在 redis 資料庫中。

    此實現方式弊端:如果瀏覽器禁用掉了 cookie 或者是非 web 請求時根本沒有 cookie 的時候,那麼如上通過cookie 管理 sessionid 的實現方式將不能夠實現 session 共享。

方案二由 httpheader 管理 sessionid

在 maven 中新增如下依賴

同3.1

在 spring 配置檔案中新增如下配置

<!-- redis 的 bean 配置如下 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"/>

<!-- 替代預設使用 cookie ,這裡使用的是 httpheader -->
<bean id="httpSessonStrategy"          class="org.springframework.session.web.http.HeaderHttpSessionStrategy"/>

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
      <property name="hostName" value="127.0.0.1" />
      <property name="port" value="6379" />
      <property name="password" value="" />
      <property name="timeout" value="3600" />
      <property name="poolConfig" ref="jedisPoolConfig" />
      <property name="usePool" value="true" />
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
       <property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>

<!-- 將 session 放入 redis -->
<bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
       <property name="maxInactiveIntervalInSeconds" value="1800" />
       <property name="httpSessionStrategy" ref="httpSessonStrategy"/>
</bean>

在 web.xml 中配置過濾器

同3.3

驗證

第一步:編寫 Controller程式碼

@RequestMapping(value = "user", method = RequestMethod.POST)
public void setUser(HttpSession session) {
    User user = new User();
    user.setName("lyf");
    user.setPassword("123");
    session.setAttribute("user", user);
}
@RequestMapping(value = "user", method = RequestMethod.GET)
public String getUser(HttpSession session) {
    User user = (User) session.getAttribute("user");
    String name = user.getName();
    return "使用者名稱稱:" + name;
}

第二步:瀏覽器中訪問 Controller

  • post 請求:localhost:8080/training/user

響應頭部如下:Response Headers:

x-auth-token:256064c7-b583-460f-bbd2-1f6dab3fd418
...

區別 Cookie 的地方在於,這種方式在響應頭資訊中添加了唯一標識欄位 x-auth-token

此時使用 redis-cli 到 redis 庫中查詢如下:

springsession:0>keys *
1) spring:session:expirations:1502597280000
2) spring:session:sessions:256064c7-b583-460f-bbd2-1f6dab3fd418
  • get 請求:localhost:8080/training/user

    請求頭部如下:Response Headers:

    x-auth-token:00ee4b6a-0aeb-42b1-a2bd-eae6f370c677

會發現此時在響應頭資訊中又重新建立了一個 x-auth-token ,因為 spring-seesion 的底層實現是在請求的時候服務端如果沒有拿到這個唯一標識,就會重新建立一個新的 x-auth-token,
並儲存到 redis 庫中。

此時使用 redis-cli 到 redis 庫中查詢如下:

springsession:0>keys *
1) spring:session:sessions:00ee4b6a-0aeb-42b1-a2bd-eae6f370c677
2) spring:session:expirations:1502597280000
3) spring:session:sessions:256064c7-b583-460f-bbd2-1f6dab3fd418
4) spring:session:expirations:1502597460000
  • 總結

因此要想獲取到 session 中的使用者資訊,需要將服務端返回的 x-auth-token 唯一識別符號附加到 Headers上,然後伺服器根據這個唯一識別符號才能找到對應的使用者資訊
在此過程的 get 請求的 Headers 中新增如下鍵值對:

  x-auth-token:256064c7-b583-460f-bbd2-1f6dab3fd418

伺服器通過 Headers 中的 x-auth-token 從 redis 庫中找到了需要的 session 物件並返回,瀏覽器顯示如下:

使用者名稱稱:lyf

因此:

Spring-session 可以控制客戶端和伺服器端之間如何進行 sessionid 的交換,這樣更加易於編寫 Restful API,因為它可以從 HTTP 頭資訊中獲取 sessionid ,而不必再依賴於 cookie 。

spring-session redis 資料結構

建立 spring session

RedisSession 在建立時設定 3 個變數 creationTime ,maxInactiveInterval ,lastAccessedTime 。maxInactiveInterval 預設值為 1800 ,表示 1800s 之內該 session 沒有被再次使用,則表明該 session 已過期。每次 session 被訪問都會更新 lastAccessedTime 的值, session 的過期計算公式:當前時間-lastAccessedTime > maxInactiveInterval.

/**
* Creates a new instance ensuring to mark all of the new attributes to be
* persisted in the next save operation.
**/
RedisSession() {
    this(new MapSession());
    this.delta.put(CREATION_TIME_ATTR, getCreationTime());
    this.delta.put(MAX_INACTIVE_ATTR, getMaxInactiveIntervalInSeconds());
    this.delta.put(LAST_ACCESSED_ATTR, getLastAccessedTime());
    this.isNew = true;
    this.flushImmediateIfNecessary();
}
public MapSession() {
    this(UUID.randomUUID().toString());
}

flushImmediateIfNecessary 判斷 session 是否需要立即寫入後端儲存。

獲取 session

spring session在 redis 裡面儲存的資料包括:

  • SET 型別的spring:session:expireations:[min]

    min 表示從 1970 年 1 月 1 日 0 點 0 分經過的分鐘數, SET 集合的 member 為 expires:[sessionId] ,表示 members 會在 min 分鐘後過期。

  • String 型別的spring:session:sessions:expires:[sessionId]

    該資料的 TTL 表示 sessionId 過期的剩餘時間,即 maxInactiveInterval。

  • Hash 型別的spring:session:sessions:[sessionId]

    session 儲存的資料,記錄了 creationTime,maxInactiveInterval,lastAccessedTime,attribute。前兩個資料是用於 session 過期管理的輔助資料結構。

獲取 session 流程:

​ 應用通過 getSession(boolean create) 方法來獲取 session 資料,引數 create 表示 session 不存在時是否建立新的 session 。 getSession 方法首先從請求的 “.CURRENT_SESSION” 屬性來獲取 currentSession ,沒有 currentSession ,則從 request 取出 sessionId ,然後讀取 spring:session:sessions:[sessionId] 的值,同時根據 lastAccessedTime 和 MaxInactiveIntervalInSeconds 來判斷這個 session 是否過期。如果 request 中沒有 sessionId ,說明該使用者是第一次訪問,會根據不同的實現,如 RedisSession ,MongoExpiringSession ,GemFireSession 等來建立一個新的 session 。

​ 另外, 從 request 取 sessionId 依賴具體的 HttpSessionStrategy 的實現,spring session 給了兩個預設的實現 CookieHttpSessionStrategy 和 HeaderHttpSessionStrategy ,即從 cookie 和 header 中取出 sessionId 。

具體的程式碼實現在第 4 章已經演示了。

session 有效期與刪除

spring session 的有效期指的是訪問有效期,每一次訪問都會更新 lastAccessedTime 的值,過期時間為lastAccessedTime + maxInactiveInterval ,也即在有效期內每訪問一次,有效期就向後延長 maxInactiveInterval。

對於過期資料,一般有三種刪除策略:

1)定時刪除,即在設定鍵的過期時間的同時,建立一個定時器, 當鍵的過期時間到來時,立即刪除。

2)惰性刪除,即在訪問鍵的時候,判斷鍵是否過期,過期則刪除,否則返回該鍵值。

3)定期刪除,即每隔一段時間,程式就對資料庫進行一次檢查,刪除裡面的過期鍵。至於要刪除多少過期鍵,以及要檢查多少個數據庫,則由演算法決定。

​ redis 刪除過期資料採用的是懶性刪除+定期刪除組合策略,也就是資料過期了並不會及時被刪除。為了實現 session 過期的及時性,spring session 採用了定時刪除的策略,但它並不是如上描述在設定鍵的同時設定定時器,而是採用固定頻率(1分鐘)輪詢刪除過期值,這裡的刪除是惰性刪除

​ 輪詢操作並沒有去掃描所有的 spring:session:sessions:[sessionId] 的過期時間,而是在當前分鐘數檢查前一分鐘應該過期的資料,即 spring:session:expirations:[min] 的 members ,然後 delete 掉 spring:session:expirations:[min] ,惰性刪除 spring:session:sessions:expires:[sessionId] 。

​ 還有一點是,檢視三個資料結構的TTL時間,spring:session:sessions:[sessionId] 和 spring:session:expirations:[min] 比真正的有效期大 5 分鐘,目的是確保當 expire key 資料過期後,監聽事件還能獲取到 session 儲存的原始資料。

@Scheduled(cron = "${spring.session.cleanup.cron.expression:0 * * * * *}")
public void cleanupExpiredSessions() {
    this.expirationPolicy.cleanExpiredSessions();
}
public void cleanExpiredSessions() {
    long now = System.currentTimeMillis();
    long prevMin = roundDownMinute(now);
    // preMin 時間到,將 spring:session:expirations:[min], 
    // set 集合中 members 包括了這一分鐘之內需要過期的所有
    // expire key 刪掉, member 元素為 expires:[sessionId]
    String expirationKey = getExpirationKey(prevMin);
    Set<Object> sessionsToExpire = this.redis.boundSetOps(expirationKey).members();
    this.redis.delete(expirationKey);
    for (Object session : sessionsToExpire) {
        // sessionKey 為 spring:session:sessions:expires:[sessionId]
        String sessionKey = getSessionKey((String) session);
        // 利用 redis 的惰性刪除策略
        touch(sessionKey);
    }
}

​ spring session 在 redis 中儲存了三個 key ,為什麼? sessions key 記錄 session 本身的資料,expires key標記 session 的準確過期時間,expiration key 保證 session 能夠被及時刪除,spring 監聽事件能夠被及時處理。

上面的程式碼展示了 session expires key 如何被刪除,那 session 每次都是怎樣更新過期時間的呢? 每一次 http 請求,在經過所有的 filter 處理過後,spring session 都會通過 onExpirationUpdated() 方法來更新 session 的過期時間, 具體的操作看下面原始碼的註釋。

public void onExpirationUpdated(Long originalExpirationTimeInMilli,
            ExpiringSession session) {
    String keyToExpire = "expires:" + session.getId();
    long toExpire = roundUpToNextMinute(expiresInMillis(session));
    if (originalExpirationTimeInMilli != null) {
        long originalRoundedUp = roundUpToNextMinute(originalExpirationTimeInMilli);
        // 更新 expirations:[min] ,兩個分鐘數之內都有這個 session ,將前一個 set 中的成員刪除
        if (toExpire != originalRoundedUp) {
            String expireKey = getExpirationKey(originalRoundedUp);
            this.redis.boundSetOps(expireKey).remove(keyToExpire);
        }
    }
    long sessionExpireInSeconds = session.getMaxInactiveIntervalInSeconds();
    String sessionKey = getSessionKey(keyToExpire);
    if (sessionExpireInSeconds < 0) {
        this.redis.boundValueOps(sessionKey).append("");
        this.redis.boundValueOps(sessionKey).persist();
        this.redis.boundHashOps(getSessionKey(session.getId())).persist();
        return;
    }
    String expireKey = getExpirationKey(toExpire);
    BoundSetOperations<Object, Object> expireOperations = this.redis
            .boundSetOps(expireKey);
    expireOperations.add(keyToExpire);
    long fiveMinutesAfterExpires = sessionExpireInSeconds
            + TimeUnit.MINUTES.toSeconds(5);
    // expirations:[min] key 的過期時間加 5 分鐘
    expireOperations.expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
    if (sessionExpireInSeconds == 0) {
        this.redis.delete(sessionKey);
    }
    else {
        // expires:[sessionId] 值為“”,過期時間為 MaxInactiveIntervalInSeconds
        this.redis.boundValueOps(sessionKey).append("");
        this.redis.boundValueOps(sessionKey).expire(sessionExpireInSeconds,
                TimeUnit.SECONDS);
    }
    // sessions:[sessionId] 的過期時間加 5 分鐘
    this.redis.boundHashOps(getSessionKey(session.getId()))
            .expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
}

相關推薦

基於 spring-session 解決分散式 session 共享問題

摘要:本文主要研究 基於 spring-seesion 解決分散式 session 的共享問題。首先講述 session 共享問題的產生背景以及常見的解決方案;然後講解本文主要研究的 spring-session 的概念和功能;接著演示了 spring-session 的兩種

Spring Boot中使用Spring Session解決分散式會話共享問題

如果你正在使用Java開發Web應用,想必你對HttpSession非常熟悉,但我們知道HpptSession預設使用記憶體來管理Session,如果將應用橫向擴充套件將會出現Session共享問題。 Spring Session提供了一套建立和管理Servlet Ht

Apache shiro叢集實現 (六)分散式集群系統下的高可用session解決方案---Session共享

      Apache Shiro的基本配置和構成這裡就不詳細說明了,其官網有說明文件,這裡僅僅說明叢集的解決方案,詳細配置:shiro web config     Apache Shiro叢集要解決2個問題,一個是session的共享問題,一個是授權

spring-session實現分散式session共享及自定義sessionid

public class MyHttpSessionStrategy implements HttpSessionStrategy { private final Logger logger = LoggerFactory.getLogger(WlwHttpSessionStrategy.class

.Net 基於Memcache叢集的分散式Session

簡述   基於Memcache的Session大家都各有各的說法,比方說:當memcached叢集發生故障(比如記憶體溢位)或者維護(比如升級、增加或減少伺服器)時,使用者會無法登入,或者被踢掉線等等,每種技術各有優缺點,只是適應的場景不同罷了。 知識點補充   伺服器Memcache配置:https://w

基於Spring+SpringMVC+Mybatis分散式敏捷開發系統架構---許可權管理系統

 README.md zheng     交流QQ群:133107819(群內含各種工具和文件下載) 前言   zheng專案創建於2016年10月4日,正在慢慢成長中,目的不僅僅是一個開發架構,而是努力打造一套從 前端模板 - 基礎框架 - 分散式架構 - 開源專案 - 持續整合 - 自動化部署 -

基於Spring+SpringMVC+Mybatis分散式敏捷開發系統架構zhen專案

目前看過做完整的專案,大家一起學習一下,詳情請點選原專案連結的地址 前言   zheng專案創建於2016年10月4日,正在慢慢成長中,目的不僅僅是一個開發架構,而是努力打造一套從 前端模板 - 基礎框架 - 分散式架構 - 開源專案 - 持續整合 - 自動化部署 -

基於spring+quartz的分散式定時任務框架

問題背景    我公司是一個快速發展的創業公司,目前有200人,主要業務是旅遊和酒店相關的,應用迭代更新週期比較快,因此,開發人員花費了更多的時間去更=跟上迭代的步伐,而缺乏了對整個系統的把控 沒有叢集之前,公司定時任務的實現方式    在初期應用的訪問量並

詳解基於Spring Boot/Spring Session/Redis的分散式Session共享解決方案

分散式Web網站一般都會碰到叢集session共享問題,之前也做過一些Spring3的專案,當時解決這個問題做過兩種方案,一是利用nginx,session交給nginx控制,但是這個需要額外工作較多;還有一種是利用一些tomcat上的外掛,修改tomcat配置檔案,讓tom

基於Spring Boot-Spring Session-Redis的分散式Session共享解決方案

分散式Web網站一般都會碰到叢集session共享問題,之前也做過一些Spring3的專案,當時解決這個問題做過兩種方案,一是利用nginx,session交給nginx控制,但是這個需要額外工作較多;還有一種是利用一些tomcat上的外掛,修改tomcat配置檔案,讓tom

Spring Boot(十一)Redis整合從Docker安裝到分散式Session共享

一、簡介 Redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API,Redis也是技術領域使用最為廣泛的儲存中介軟體,它是「Remote Dictionary Service」首字母縮寫,也就是「遠端字典服務」。 Red

使用redis實現session共享(基於Spring Boot)

Session 共享 什麼是 Session 由於 HTTP 協議是無狀態的協議,所以服務端需要記錄使用者的狀態時,就需要用某種機制來識具體的使用者。Session 是另一種記錄客戶狀態的機制,不同的是 Cookie 儲存在客戶端瀏覽器中,而 Session 儲存在伺服器上。客戶端瀏覽器訪問

分散式Session共享解決方案

分散式Session解決方案 Author:SimpleWu 分散式Session一致性? 說白了就是伺服器叢集Session共享的問題 Session的作用? Session 是客戶端與伺服器通訊會話跟蹤技術,伺服器與客戶端保持整個通訊的會話基本資訊。 客戶端在第一次訪問服務端的時候,服務端會響

分散式Session共享解決方案.直的一看

Author:SimpleWu分散式Session一致性? 說白了就是伺服器叢集Session共享的問題 Session的作用? Session 是客戶端與伺服器通訊會話跟蹤技術,伺服器與客戶端保持整個通訊的會話基本資訊。 客戶端在第一次訪問服務端的時候,服務端會響應一個sessionId並且將它存入

spring boot整合redis實現shiro的分散式session共享

我們知道,shiro是通過SessionManager來管理Session的,而對於Session的操作則是通過SessionDao來實現的,預設的情況下,shiro實現了兩種SessionDao,分別為CachingSessionDAO和MemorySessionDAO,

基於nginx tomcat redis分散式web應用的session共享配置

apply plugin: 'java' apply plugin: 'maven' apply plugin: 'signing' group = 'com.orangefunction' version = '2.0.0' repositories { mavenCentral

Spring Data實現分散式共享session

1、自定義HttpSession實現Session https://www.cnblogs.com/youzhibing/p/7348337.html 2、Spring整合Jedis2.9(叢集帶密碼版) https://blog.csdn.net/cslucifer/article/d

Spring Session + Redis實現分散式Session共享

通常情況下,Tomcat、Jetty等Servlet容器,會預設將Session儲存在記憶體中。如果是單個伺服器例項的應用,將Session儲存在伺服器記憶體中是一個非常好的方案。但是這種方案有一個缺點,就是不利於擴充套件。 目前越來越多的應用採用分散式部署,

利用spring session解決共享Session問題

1.共享Session問題 HttpSession是通過Servlet容器建立和管理的,像Tomcat/Jetty都是儲存在記憶體中的。而如果我們把web伺服器搭建成分散式的叢集,然後利用LVS或Nginx做負載均衡,那麼來自同一使用者的Http請求將有可能被分發到兩個不

使用Spring Session實現分散式Session共享

之前在分散式環境下需要解決session共享的問題,更多的時候我們是使用servlet容器例如tomcat提供的叢集配置來解決session的複製問題。今天介紹一種簡單的解決方案。 1 1. 新增依賴 <dependency> <gro