解決應用伺服器叢集的Session問題
使用者使用網站的服務,基本上需要瀏覽器與Web伺服器的多次互動。
HTTP協議
本身是無狀態的
,需要基於HTTP協議支援會話狀態(Session State)
的機制。而這樣的機制應該可以使Web伺服器從多次單獨的HTTP請求中看到“會話”,也就是知道請求是來自哪個會話的。具體實現方式為:在會話開始時,分配一個唯一的會話標識(SessionId),通過Cookie把這個標識告訴伺服器,以後每次請求的時候,瀏覽器都會帶上這個會話標識來告訴Web伺服器請求是屬於哪個會話的。在Web伺服器上,各個會話有獨立的儲存,儲存不同會話的資訊。如果遇到禁用Cookie的情況,一般的做法就是把這個會話標識放到URL的引數中。
單臺應用伺服器
當一個帶有會話標識的HTTP請求到了Web伺服器後,需要在HTTP請求的處理過程中找到對應的會話資料(Session)。而問題在於
會話資料是需要儲存在單機上的
。在面對應用伺服器叢集時,如果我第一次訪問網站時請求通過負載均衡裝置落到了伺服器A,那麼我的Session就建立在伺服器A上了,如果我們不做處理,就不能保證接下來的請求每次都落在伺服器A上了。
應用伺服器叢集
1. Session Sticky
使負載均衡器能夠根據每次請求的會話標識來進行請求轉發。
需要在負載均衡伺服器上儲存會話到具體Web伺服器的對映。
Session Sticky
這種方法非常簡單,但是有以下幾個問題:
1.如果有一臺Web伺服器宕機或者重啟,那麼這臺機器上的會話資料會丟失。如果會話中有登陸狀態資訊,那麼使用者就要重新登入了。
2.會話標識是應用程式的資訊,負載均衡伺服器要將同一個會話的請求都儲存到一個Web伺服器上的話需要進行應用層(OSI模型第7層)的解析,這個開銷比第4層(傳輸層)的交換大。
3.負載均衡器變成了有狀態的節點,要儲存會話到Web伺服器的對映,比無狀態節點記憶體消耗更大,容災會更麻煩。
2.Session Replication
Web伺服器之間增加了會話資料的同步,應用伺服器叢集中的每一臺伺服器上都有一份會話資料。
Session Replication
但是也帶來了一些問題:
1.同步Session資料造成了網路頻寬的開銷。只要Session資料有變化就需要同步,機器數越多,同步帶來的網路頻寬開銷越大。
2.每臺Web伺服器都儲存所有額Session資料,在很多人同時訪問網站的時候,每臺機器用於儲存Session資料的內容佔用會很嚴重。
3.Session資料集中儲存
不同的伺服器從同樣的地方來獲取Session。會話請求經過負載均衡伺服器後,不會被固定在同樣的Web伺服器上,而是放在了一個集中儲存的地方。Web伺服器使用Session資料時,也是從這個集中儲存Session資料的地方來讀取。
Session資料集中儲存
這個方案解決了第一種方案的記憶體
問題,也第二種方案佔用網路頻寬
的情況要好。但是依然存在一些問題:
1.讀寫Session資料引入了網路操作,相對於本機的資料讀取來說,問題在於存在時延和不穩定性。
2.如果集中儲存Session的機器或者叢集有問題,就會影響我們的應用。
4.Cookie Based
把Session資料放在Cookie中,在Web伺服器上從Cookie中生成對應的Session資料。
Cookie Based
這個方案不會依賴外部儲存系統,也就不存在從外部系統獲取、寫入資料的網路時延和不穩定性了。
不過依然存在不足:
1.Cookie長度的限制。Cookie長度會限制Session資料的長度。
2.安全性。Session資料是服務端資料, 這個方案讓服務端資料到了外部網路和服務端。
3.頻寬消耗。資料中心整體外部頻寬的消耗。
4.效能影響。每次HTTP請求和響應都帶有Session資料。
小結
這4種方案都是可用的方案,不過對於大型網站來說,Session Sticky和Session資料集中儲存是比較好的方案,而這兩個方案又各有優勢,需要在具體的場景中做出選擇和權衡。
以上內容來自《大型網站系統與Java中介軟體實踐》