分布式架構下的session共享,也可以稱作分布式session一致性;關於這個問題,和大家說一說解決方案(如果有其他的方案,可以留言討論)。
session的作用
如果大家做過web應用開發的話,應該對session比較熟悉;服務器會為每個用戶創建一個會話,存儲用戶的相關信息,以便在后面的請求中,可以夠定位到同一個上下文。
例如用戶在登錄之后,再進行頁面跳轉的時候,存儲在session中的信息會一直保持,如果用戶還沒有session,那么服務器會創建一個session對象,直到會話過期或主動放棄后(退出),服務器才會把session終止掉。
分布式架構中的session問題
在N年前,那個都是單個服務器的年代,session直接保存在服務器中,是一點問題沒有的,而且實現起來很容易。
但是隨着分布式架構的流行,單個服務器已經不能滿足系統的需要了,通常都會把系統部署在多台服務器上,通過負載均衡把請求分發到其中的一台服務器上,這樣很可能同一個用戶的請求被分發到不同的服務器上,因為session是保存在服務器上的,那么很有可能第一次請求訪問的A服務器,創建了session,但是第二次訪問到了B服務器,這時就會出現取不到session的情況。
於是,分布式架構中,session共享就成了一個很大的問題。
解決方案
- 不要有session:大家可能覺得我說了句廢話,但是確實在某些場景下,是可以沒有session的,其實在很多接口類系統當中,都提倡【API無狀態服務】;也就是每一次的接口訪問,都不依賴於session、不依賴於前一次的接口訪問;
- 存入cookie中:將session存儲到cookie中,但是缺點也很明顯,例如每次請求都得帶着session,數據存儲在客戶端本地,是有風險的;
- session同步:對個服務器之間同步session,這樣可以保證每個服務器上都有全部的session信息,不過當服務器數量比較多的時候,同步是會有延遲甚至同步失敗;
- 使用Nginx(或其他復雜均衡軟硬件)中的ip綁定策略,同一個ip只能在指定的同一個機器訪問,但是這樣做風險也比較大,而且也是去了負載均衡的意義;
- 我們現在的系統會把session放到Redis中存儲,雖然架構上變得復雜,並且需要多訪問一次Redis,但是這種方案帶來的好處也是很大的:實現session共享,可以水平擴展(增加Redis服務器),服務器重啟session不丟失(不過也要注意session在Redis中的刷新/失效機制),不僅可以跨服務器session共享,甚至可以跨平台(例如網頁端和APP端)。
米寸陽光 科技公司工程師
什么是session?
服務器為每個用戶創建一個會話,存儲用戶的相關信息,以便多次請求能夠定位到同一個上下文。這樣,當用戶在應用程序的 Web 頁之間跳轉時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去。
當用戶請求來自應用程序的 Web 頁時,如果該用戶還沒有會話,則 Web 服務器將自動創建一個 Session 對象。當會話過期或被放棄后,服務器將終止該會話。
Web開發中,web-server可以自動為同一個瀏覽器的訪問用戶自動創建session,提供數據存儲功能。最常見的,會把用戶的登錄信息、用戶信息存儲在session中,以保持登錄狀態。
什么是session一致性問題?
只要用戶不重啟瀏覽器,每次http短連接請求,理論上服務端都能定位到session,保持會話。
分布式session:
單服務器web應用中,session信息只需存在該服務器中,這是我們前幾年最常接觸的方式,但是近幾年隨着分布式系統的流行,單系統已經不能滿足日益增長的百萬級用戶的需求,集群方式部署服務器已在很多公司運用起來,當高並發量的請求到達服務端的時候通過負載均衡的方式分發到集群中的某個服務器,這樣就有可能導致同一個用戶的多次請求被分發到集群的不同服務器上,就會出現取不到session數據的情況,於是session的共享就成了一個問題。
這個時候就需要解決Session一致性。
Session一致性解決方案:
分布式Session共享的4類技術方案,與優劣勢比較
1、session復制
session復制是早期的企業級的使用比較多的一種服務器集群session管理機制。
應用服務器開啟web容器的session復制功能,在集群中的幾台服務器之間同步session對象,使得每台服務器上都保存所有的session信息,這樣任何一台宕機都不會導致session的數據丟失,服務器使用session時,直接從本地獲取。
簡介:將一台機器上的Session數據廣播復制到集群中其余機器上
session復制使用場景:機器較少,網絡流量較小
優點:實現簡單、配置較少、當網絡中有機器Down掉時不影響用戶訪問
缺點:廣播式復制到其余機器有一定廷時,帶來一定網絡開銷。
這種方式在應用集群達到數千台的時候,就會出現瓶頸,每台都需要備份session,出現內存不夠用的情況。
2、session綁定
利用hash算法,比如nginx的ip_hash,使得同一個Ip的請求分發到同一台服務器上。
session綁定使用場景:機器數適中、對穩定性要求不是非常苛刻
優點:實現簡單、配置方便、沒有額外網絡開銷
缺點:網絡中有機器Down掉時、用戶Session會丟失、容易造成單點故障。
這種方式不符合對系統的高可用要求,因為一旦某台服務器宕機,那么該機器上的session也就不復存在了,用戶請求切換到其他機器后么有session,無法完成業務處理。
3、利用cookie記錄session
session記錄在客戶端,每次請求服務器的時候,將session放在請求中發送給服務器,服務器處理完請求后再將修改后的session響應給客戶端,這里的客戶端就是cookie。
缺點
比如受cookie大小的限制,能記錄的信息有限;
每次請求響應都需要傳遞cookie,影響性能,如果用戶關閉cookie,訪問就不正常。
優點:
cookie的簡單易用,可用性高,支持應用服務器的線性伸縮,而大部分要記錄的session信息比較小,因此事實上,許多網站或多或少的在使用cookie記錄session。
4、session服務器
session服務器可以解決上面的所有的問題,利用獨立部署的session服務器(集群)統一管理session,服務器每次讀寫session時,都訪問session服務器。
這種解決方案事實上是應用服務器的狀態分離,分為無狀態的應用服務器和有狀態的session服務器,然后針對這兩種服務器的不同特性分別設計架構。
對於有狀態的session服務器,一種比較簡單的方法是利用分布式緩存(redis、memcached), 或者存儲在數據庫(如MySQL)等。在這些產品的基礎上進行包裝,使其符合session的存儲和訪問要求。
如果業務場景對session管理有比較高的要求,比如利用session服務基層單點登錄(sso),用戶服務器等功能,需要開發專門的session服務管理平台。
session服務器使用場景:集群中機器數多、網絡環境復雜。
優點:可靠性好
缺點:實現復雜、穩定性依賴於緩存的穩定性、Session信息放入緩存時要有合理的策略寫入。