登入模組 分布式會話設計文件

2021-10-23 02:01:37 字數 2787 閱讀 6406

session複製

session繫結

spring-security集中式會話的設計

會話保持

我們都知道http是無狀態協議,如果我們在同一**進行連續兩次請求時,伺服器是無法識別兩次請求的相關性,尤其是需要登入認證的**,如果第乙個請求是登入請求,伺服器認證成功,然後進行第二次請求,服務端仍然無法識別該請求的具體身份,就會返回「403 forbidden」或者重定向至登入頁面,然後需要進行傳送登入請求進行重定向至該頁面,這無疑是極差的使用者體驗。所以我們需要存在乙個伺服器能識別的憑據,來表明自己的認證身份,一般存在兩種方式:

cookie:一般儲存在客戶端,每次請求時需要攜帶cookie,優點:cookie儲存在客戶端,緩解服務端會話儲存壓力;缺點:cookie可能會很臃腫,降低請求效率,而且其中可能儲存了一些敏感資訊,安全度不高。

session:一般儲存在服務端,客戶端需要在首部cookie或者查詢引數中攜帶session id;優點:服務端儲存session資訊,只對外暴露session id,能較好保護資訊;缺點:服務端需要儲存較多的會話資訊。

分布式會話解決方案

cookie不存在集群session共享的問題,因為cookie中已經儲存足夠的能識別使用者身份的資訊,每台主機的應用服務都能解析相應cookie並獲取到其中的使用者資訊。而對於伺服器儲存的session資訊,伺服器的會話資訊都是在本地儲存的,但是我們對集群進行負載均衡時就會出現問題,如果登入請求和後續請求不是**到同一臺伺服器進行處理的話,就會出現會「403 forbbiden」的情況。為了保證應用服務的可伸縮性以及服務可用性,能支援平滑的橫向擴充套件,需要保證能在集群各個主機間進行共享。

集中式會話

把 session 持久化到資料庫

使用儲存中介軟體

記憶體資料庫通常被用作快取資料資訊,同樣我們可以使用它來儲存會話資訊,讀寫效率都特別高,這種中介軟體比如redis、memcache等。

session複製

這是通過web容器之間進行session資訊的複製同步,每台伺服器都具有全部的session資訊,這種方式需要占用大量的頻寬資源,不適合在大型集群中使用。

session繫結

也稱為粘性會話(sticky session),這個本不屬於session共享部分,但同樣能解決集群中session的訪問問題,這就是負載均衡策略中的ip_hash,負載均衡裝置會將來自同乙個ip的請求都**至同乙個應用伺服器中,而session只需要儲存在該伺服器即可。

spring-security應用需要區分spring-security會話和tomcat會話,其中spring-security會話和tomcat會話具有相同的會話id,當客戶端向服務端進行請求時,都會生成乙個tomcat會話,只有當客戶端進行登入認證後,tomcat會話才會攜同憑證一起註冊到spring-security的會話中心中。兩種會話具有相同的生命週期,spring-security的會話註冊中心會監聽tomcat會話銷毀事件,當其接收到會話destroyedevent事件時,會移除相關的會話資訊。

其中principal是指使用者的憑證資訊,一般在系統中體現為使用者id或者使用者名稱,我們會在redis中儲存相關使用者名稱以及一些不可變的資訊。目前並未設定賬號的同時登入裝置數限制,使用者會話需要進行set儲存,以相容多台裝置同時登入的情況,保證所有登入會話id皆可用。會話資訊主要儲存使用者名稱以及上次訪問時間,最近訪問時間可以用於支援會話過期策略。

下圖是對redissessionregistry的會話註冊中心的簡易設計,具體實現主要就是通過實現sessionregistry介面進行實現:

我們考慮這樣一種情況,一台伺服器出現了一些問題,我們需要重啟機器並重新部署服務,web容器關閉時會對會話資訊進行銷毀,這就導致伺服器可能會誤刪一些其他伺服器仍然活躍的會話,對於這種情況,我們需要在redis中儲存持有該會話的主機列表,只有當列表中只有本機(即只有乙個註冊主機)時,才能進行會話移除,下圖為redis儲存結構:

為了保證會話id在每台伺服器的可用性,我們需要擴充套件tomcat的sessionmanager,使其將session查詢範圍從本機,延伸到redis註冊中心,保證各台機器已認證的會話id都能被其他機器識別使用。由於tomcat在會話過期後會自動移除會話,移除會話的策略是通過判斷上次訪問時間距離現在時間是否已經超過會話的最大生存時間,所以我們請求某台主機時,需要讓其他主機也同時接收到該事件,然後進行會話訪問更新。通過redis pub/sub將乙個主機的訪問事件發布到其他機器,其他主機接收到該事件後進行重新整理session的操作,保證會話生命週期的同步性。

這個設計目前並非最優,但是基本可以滿足需要,我們還可以考慮思考[1]部分進行改良,但這個改良只是降低了系統的複雜性,由於儲存結構的改變和和網路通訊延遲的增加,能否保持較高的訪問效能還有待商榷。

一些思考:

1、是否可以通過對standardsession進行擴充套件,將會話上次請求時間直接從redis中獲取,以及一些引數也可以之間儲存到redis中去,這樣可以省去redis pub/sub進行會話同步的部分。

2、對於sessionregistry,由於我們不需要使用到密碼等其他資訊…

3、使用memcache是否會具有比redis更高的效能:msm解決方案

2、3、

分布式會話

上週用了整整一周時間,搞了乙個分布式會話的東西。儘管到了最後沒有完成的很完美,有一點點小問題延誤了上線,不過這對我自己來說,已經非常滿足了。拿出來分享一下。當今,單節點架構的專案是很容易當掉的。網路攻擊 競爭公司 不正當訪問 使用者量的大幅度提公升以及快速迭代 產品不斷打補丁上線,這都對系統的架構提...

分布式系統下登入會話控制系統設計

背景介紹 本人目前就職於中國電信旗下第三方支付公司 甜橙金融的資訊科技部客戶平台,該平台負載管理公司近2億使用者的個人資訊與鑑權憑證,並提供相關的介面能力。我主要負責該平台的需求分析與設計工作。甜橙金融通過自主研發,經過一段時間的積累,目前主要業務已經執行在第三代基礎技術平台。該平台採用分布式架構,...

分布式文件儲存

路由乙個文件到乙個分片中 當索引乙個文件的時候,文件會被儲存到乙個主分片中。elasticsearch 如何知道乙個文件應該存放到哪個分片中呢?當我們建立文件時,它如何決定這個文件應當被儲存在分片1還是分片2中呢?首先這肯定不會是隨機的,否則將來要獲取文件的時候我們就不知道從何處尋找了。實際上,這個...