SpringSession系列-分佈式 session 實現方案及 SpringSession 功能分析

上一篇文章 SpringSession:集成SpringBoot 中介紹瞭如何在SpringBoot中來集成 SpringSession,整個過程很是簡單,同時也簡單分析了下SpringSession的做用原理。繼上一篇實踐以後,本文主要來分析 SpringSession 的原理。html

一、從 session 的一致性方案提及

關於 sessioncookie 的一些知識,你們能夠參考下我以前寫的一篇文章:聊一聊session和cookiehtml5

Session做爲服務器端使用的一種記錄客戶端狀態的機制,其對客戶端是透明的;可是Session 的正常運做仍然須要客戶端瀏覽器的支持。咱們都知道,HTTP協議是無狀態的,Session不能依據HTTP鏈接來判斷是否爲同一客戶,所以服務器須要向客戶端瀏覽器發送一個識別標誌(sessionId),這個識別標誌經過是經過Cookie機制來完成。git

1.一、session 一致性問題的由來

當用戶首次訪問咱們的Servlet時,應用服務器端會給用戶建立一個獨立的Session,而且存儲在內存中。這種狀況在單應用服務器場景下是能夠知足的(這裏不討論其一個弊端,就是內存佔用給服務器帶來的壓力的問題)。在集羣場景下,這種機制就會到來問題:github

1.1.一、單機場景

由於是一臺應用服務器,用戶的每次請求都是由這臺機器來處理,因此不會有session共享問題。redis

1.1.二、集羣場景

假設如今集羣中有三臺機器,(從上到下:A->B->C)。當前用戶首次發起訪問時,請求被分配到 A 機器處理,Session數據被寫入 A 機器的內存中;當再次發起訪問 時,請求被分配的 B 處理,但此時 B 內存中並無當前用戶的任何數據,這樣就出現了session不一致的狀況了。spring

1.二、Session 一致性問題的方案

對於當前服務化、單元化應用盛行的時代,簡單的內存型的 Session 已經不可以知足咱們的要求了。那麼咱們就須要尋求一種方案來替換目前單機內存存儲實現的方案。數據庫

1.2.1 基於 IP-HASH 的實現機制

在 1.1.2 中由於咱們沒法知道請求會被分配到哪臺機器來處理,因此會致使session不一致的問題出現。若是咱們能夠解決讓每一個用戶的請求可以固定的打到某一臺機器上,那麼上面提到的問題其實也就不存在了。IP-HASH 就是這樣一種方案。經過對請求的客戶端 IP 進行 HASH 計算,並將計算結果映射到具體一臺機器,這樣就能夠將請求固定分配到某一臺機器上,從而有效的避免session一致性問題的出現。瀏覽器

這種方案的好處在於:緩存

  • 不須要修改任何應用代碼,0 侵入。
  • 安全性高,不依賴其餘三方緩存框架帶來的風險
  • 成本低

可是問題也很明顯,這種方式其實是規避了session一致性問題的出現,並不是是針對session一致性問題給出的解決方案。主要問題:安全

  • 基於應用內存,會給應用服務器帶來必定的壓力
  • 服務重啓會致使session數據丟失
  • 不利於水平擴展,水平擴展也可能丟失session
  • 存在單點負載高的狀況,就是多數請求通過HASH計算以後打到同一臺機器,而其餘機器處於空閒狀態。

1.2.2 session 複製

這種方式的實現原理是應用服務器建立session以後經過組播的方式將session發送到組播地址內的其餘應用服務器上。這種方式相較於IP-HASH 的方式要靠譜一點:

  • 一樣不須要更改任何業務代碼
  • 可以適應多種負載策略
  • 機器重啓或者宕機以後不怕丟失,由於有冗餘備份

可是這種方式也有比較大的問題:

  • 首先就是服務器之間同步session會佔用必定的網絡資源,同時session在不一樣的機器之間進行同步存在延遲。
  • 仍是基於內存存儲,侷限於機器內存容量影響,水平擴展能力差
  • 服務器內存由於須要存儲其餘機器上的session數據,對內存的消耗會隨着集羣的規模變大而變大,可能會致使機器頻繁觸發GC

1.2.3 藉助三方緩存框架實現 session 集中管理

上面兩種方式都是有服務器本身來管理session的,主要問題仍是在於對於性能和內存的影響。而這種方式的原理是將session託管給三方軟件(如redis)來統一管理。這種方式能夠有效的解決性能、內存佔用以及水平擴展等問題。可是由於引入了三方軟件,在實現複雜度、運維成本等方面會有所增長。

目前所接觸到的分佈式session的實現方案,大多都是基於這種方式來實現的;SpringSession 也不例外。

二、SpringSession 功能結構分析

前面對分佈式場景下的 Session一致性問題進行了說明,並對解決Session一致性的問題的幾種策略進行的分析(有點糙,網上這些知識有不少)。在瞭解這些背景以後,咱們來看下 SpringSession 的實現原理。

2.1 簡介

Spring Session 提供了用於管理用戶會話信息的API和實現,在不依賴特定於應用程序容器的解決方案的狀況下,使得支持羣集會話變得更加簡單。它還提供了透明的集成:

  • 容許以應用程序容器(Tomcat等)中立的方式替換 HttpSesseion,支持在 headers中提供 session IDs來使用 RESTful API
  • 提供在接收 WebSocket 消息時保持HTTP 會話存活的能力
  • 容許以應用程序容器中立的方式替換 Spring WebFluxWebSession

以上來自官網文檔翻譯 Spring Session

2.2 模塊

Spring Session 主要包括 4 個模塊:

  • spring-session-core :提供了 Spring Session 核心功能和API
  • spring-session-data-redis:以 redis 做爲存儲機制的 SessionRepository 實現
  • spring-session-hazelcast:以 Hazelcast 做爲存儲機制的 SessionRepository 實現
  • spring-session-jdbc:以關係型數據庫做爲存儲機制的 SessionRepository 實現

整體來講就是 核心API+存儲實現;工程模塊截圖以下:

2.3 功能結構

SpringSession總體上能夠分爲三塊:

  • 對於Web層的處理,這裏包括對於請求的重寫,自定義的filter加入到filter chain,cookie處理,http header處理等
  • 公共基礎封裝,好比存儲類的頂層抽象接口定義,自定配置,事件處理等。
  • 存儲部分,這部分其實是對公共基礎封裝接口的實現,提供了豐富的存儲實現,包括redis,內存存儲,jdbc等。

2.4 多 session 支持

對於經常使用的分佈式session,在實現上通常會依賴於 cookie。可是在 springsession 中提供了基於header來傳遞jessionID的策略實現。同時在 2.0.4 版本以前,對於同一個瀏覽器同一個網站,springsession 支持多個session問題,可是在此版本以後拋棄了對於對 session 的支持。關於更多關於多session支持能夠查看 SpringSession 的官方文檔

小結

本文對分佈式 session 的幾種實現策略進行了簡單的介紹。對於分佈式 session 而言,如何解決一致性問題是關鍵,目前我見過的絕大多數方案均是以 【藉助三方緩存框架實現 session 集中管理】 這種來實現的,包括本系列文章中所要介紹的 SpringSession。

除分佈式session一致性方式解決方案的介紹以外,做爲SpringSession 的第二篇文章,在這裏簡單分析了下Springsession的功能模塊,以便後續展開對源碼的分析。

相關文章
相關標籤/搜索