上一篇文章 SpringSession:集成SpringBoot 中介紹瞭如何在SpringBoot
中來集成 SpringSession
,整個過程很是簡單,同時也簡單分析了下SpringSession
的做用原理。繼上一篇實踐以後,本文主要來分析 SpringSession
的原理。html
關於 session
和cookie
的一些知識,你們能夠參考下我以前寫的一篇文章:聊一聊session和cookie。html5
Session
做爲服務器端使用的一種記錄客戶端狀態的機制,其對客戶端是透明的;可是Session
的正常運做仍然須要客戶端瀏覽器的支持。咱們都知道,HTTP
協議是無狀態的,Session
不能依據HTTP
鏈接來判斷是否爲同一客戶,所以服務器須要向客戶端瀏覽器發送一個識別標誌(sessionId
),這個識別標誌經過是經過Cookie
機制來完成。git
當用戶首次訪問咱們的Servlet
時,應用服務器端會給用戶建立一個獨立的Session
,而且存儲在內存中。這種狀況在單應用服務器場景下是能夠知足的(這裏不討論其一個弊端,就是內存佔用給服務器帶來的壓力的問題)。在集羣場景下,這種機制就會到來問題:github
由於是一臺應用服務器,用戶的每次請求都是由這臺機器來處理,因此不會有session
共享問題。redis
假設如今集羣中有三臺機器,(從上到下:A->B->C)。當前用戶首次發起訪問時,請求被分配到 A 機器處理,Session
數據被寫入 A 機器的內存中;當再次發起訪問 時,請求被分配的 B 處理,但此時 B 內存中並無當前用戶的任何數據,這樣就出現了session
不一致的狀況了。spring
對於當前服務化、單元化應用盛行的時代,簡單的內存型的 Session
已經不可以知足咱們的要求了。那麼咱們就須要尋求一種方案來替換目前單機內存存儲實現的方案。數據庫
在 1.1.2 中由於咱們沒法知道請求會被分配到哪臺機器來處理,因此會致使session
不一致的問題出現。若是咱們能夠解決讓每一個用戶的請求可以固定的打到某一臺機器上,那麼上面提到的問題其實也就不存在了。IP-HASH
就是這樣一種方案。經過對請求的客戶端 IP
進行 HASH
計算,並將計算結果映射到具體一臺機器,這樣就能夠將請求固定分配到某一臺機器上,從而有效的避免session
一致性問題的出現。瀏覽器
這種方案的好處在於:緩存
可是問題也很明顯,這種方式其實是規避了session
一致性問題的出現,並不是是針對session
一致性問題給出的解決方案。主要問題:安全
session
數據丟失session
HASH
計算以後打到同一臺機器,而其餘機器處於空閒狀態。這種方式的實現原理是應用服務器建立session
以後經過組播的方式將session
發送到組播地址內的其餘應用服務器上。這種方式相較於IP-HASH
的方式要靠譜一點:
可是這種方式也有比較大的問題:
session
會佔用必定的網絡資源,同時session
在不一樣的機器之間進行同步存在延遲。session
數據,對內存的消耗會隨着集羣的規模變大而變大,可能會致使機器頻繁觸發GC
。上面兩種方式都是有服務器本身來管理session
的,主要問題仍是在於對於性能和內存的影響。而這種方式的原理是將session
託管給三方軟件(如redis
)來統一管理。這種方式能夠有效的解決性能、內存佔用以及水平擴展等問題。可是由於引入了三方軟件,在實現複雜度、運維成本等方面會有所增長。
目前所接觸到的分佈式session
的實現方案,大多都是基於這種方式來實現的;SpringSession
也不例外。
前面對分佈式場景下的 Session
一致性問題進行了說明,並對解決Session
一致性的問題的幾種策略進行的分析(有點糙,網上這些知識有不少)。在瞭解這些背景以後,咱們來看下 SpringSession
的實現原理。
Spring Session
提供了用於管理用戶會話信息的API
和實現,在不依賴特定於應用程序容器的解決方案的狀況下,使得支持羣集會話變得更加簡單。它還提供了透明的集成:
Tomcat
等)中立的方式替換 HttpSesseion
,支持在 headers
中提供 session IDs
來使用 RESTful API
。WebSocket
消息時保持HTTP
會話存活的能力Spring WebFlux
的 WebSession
。以上來自官網文檔翻譯 Spring Session
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
+存儲實現;工程模塊截圖以下:
SpringSession總體上能夠分爲三塊:
對於經常使用的分佈式session,在實現上通常會依賴於 cookie。可是在 springsession 中提供了基於header來傳遞jessionID的策略實現。同時在 2.0.4 版本以前,對於同一個瀏覽器同一個網站,springsession 支持多個session
問題,可是在此版本以後拋棄了對於對 session 的支持。關於更多關於多session支持能夠查看 SpringSession 的官方文檔。
本文對分佈式 session 的幾種實現策略進行了簡單的介紹。對於分佈式 session 而言,如何解決一致性問題是關鍵,目前我見過的絕大多數方案均是以 【藉助三方緩存框架實現 session 集中管理】 這種來實現的,包括本系列文章中所要介紹的 SpringSession。
除分佈式session一致性方式解決方案的介紹以外,做爲SpringSession 的第二篇文章,在這裏簡單分析了下Springsession的功能模塊,以便後續展開對源碼的分析。