集群session管理問題


轉自:http://book.51cto.com/art/201405/439557.htm

先來看一下什么是Session。

用戶使用網站的服務,基本上需要瀏覽器與Web 服務器的多次交互。HTTP 協議本身是無狀態的,需要基於HTTP 協議支持會話狀態(Session State)的機制。而這樣的機制應該可以使Web 服務器從多次單獨的HTTP 請求中看到“會話”,也就是知道哪些請求是來自哪個會話的。具體實現方式為:在會話開始時,分配一個唯一的會話標識(SessionId),通過Cookie 把這個標識告訴瀏覽器,以后每次請求的時候,瀏覽器都會帶上這個會話標識來告訴Web 服務器請求是屬於哪個會話的。在Web 服務器上,各個會話有獨立的存儲,保存不同會話的信息。如果遇到禁用Cookie 的情況,一般的做法就是把這個會話標識放到URL 的參數中。我們可以通過圖2-8 來看一下上述過程。

當我們的應用服務器從一台變到兩台后,如同圖2-7 中的結構,我們就會遇到Session的問題了。具體是指什么問題呢?

我們來看圖2-9,當一個帶有會話標識的HTTP 請求到了Web 服務器后,需要在HTTP請求的處理過程中找到對應的會話數據(Session)。而問題就在於,會話數據是需要保存在單機上的。

在圖2-9 所示的網站中,如果我第一次訪問網站時請求落到了左邊的服務器,那么我的Session 就創建在左邊的服務器上了,如果我們不做處理,就不能保證接下來的請求每次都落在同一邊的服務器上了,這就是Session 問題。

我們看看這個問題的幾種解決方案。

1.Session Sticky

在單機的情況下,會話保存在單機上,請求也都是由這個機器處理,所以不會有問題。Web 服務器變成多台以后,如果保證同一個會話的請求都在同一個Web 服務器上處理,那么對這個會話的個體來說,與之前單機的情況是一樣的。

如果要做到這樣,就需要負載均衡器能夠根據每次請求的會話標識來進行請求轉發,如圖2-10 所示,稱為Session Sticky 方式。 

這個方案本身非常簡單,對於Web 服務器來說,該方案和單機的情況是一樣的,只是我們在負載均衡器上做了“手腳”。這個方案可以讓同樣Session 的請求每次都發送到同一個服務器端處理,非常利於針對Session 進行服務器端本地的緩存。不過也帶來了如下幾個問題:

如果有一台Web 服務器宕機或者重啟,那么這台機器上的會話數據會丟失。如果會話中有登錄狀態數據,那么用戶就要重新登錄了。

會話標識是應用層的信息,那么負載均衡器要將同一個會話的請求都保存到同一個Web服務器上的話,就需要進行應用層(第7 層)的解析,這個開銷比第4 層的交換要大。負載均衡器變為了一個有狀態的節點,要將會話保存到具體Web 服務器的映射。和無狀態的節點相比,內存消耗會更大,容災方面會更麻煩。

這種方式我們稱為Session Sticky。打個比方來說,如果說Web 服務器是我們每次吃飯的飯店,會話數據就是我們吃飯用的碗筷。要保證每次吃飯都用自己的碗筷的話,我就把餐具存在某一家,並且每次都去這家店吃,是個不錯的主意。

2.Session Replication

如果我們繼續以去飯店吃飯類比,那么除了前面的方式之外,如果我在每個店里都存放一套自己的餐具,不就可以更加自由地選擇飯店了嗎?Session Replication 就是這樣的一種方式,這一點從字面上也很容易看出來。

先看一下圖2-11,如下。 

可以看到,在Session Replication 方式中,不再要求負載均衡器來保證同一個會話的多次請求必須到同一個Web 服務器上了。而我們的Web 服務器之間則增加了會話數據的同步。通過同步就保證了不同Web 服務器之間的Session 數據的一致。就如同每家飯店都有我的碗筷,我就能隨便選擇去哪家吃飯了。

一般的應用容器都支持(包括了商業的和開源的)Session Replication 方式,與Session Sticky 方案相比,Session Replication 方式對負載均衡器沒有那么多的要求。不過這個方案本身也有問題,而且在一些場景下,問題非常嚴重。我們來看一下這些問題。

同步Session 數據造成了網絡帶寬的開銷。只要Session 數據有變化,就需要將數據同步到所有其他機器上,機器數越多,同步帶來的網絡帶寬開銷就越大。

每台Web 服務器都要保存所有的Session 數據,如果整個集群的Session 數很多(很多人在同時訪問網站)的話,每台機器用於保存Session 數據的內容占用會很嚴重。這就是Session Replication 方案。這個方案是靠應用容器來完成Session 的復制從而使得應用解決Session 問題的,應用本身並不用關心這個事情。不過,這個方案不適合集群機器數多的場景。如果只有幾台機器,用這個方案是可以的。

3.Session 數據集中存儲

同樣是希望同一個會話的請求可以發到不同的Web 服務器上,剛才的Session Replication是一種方案,還有另一種方案就是把Session 數據集中存儲起來,然后不同Web 服務器從同樣的地方來獲取Session。大概的結構如圖2-12 所示。

可以看到,與Session Replication 方案一樣的部分是,會話請求經過負載均衡器后,不會被固定在同樣的Web 服務器上。不同的地方是,Web 服務器之間沒有了Session 數據復制,並且Session 數據也不是保存在本機了,而是放在了另一個集中存儲的地方。這樣,不論是哪台Web 服務器,也不論修改的是哪個Session 數據,最終的修改都發生在這個集中存儲的地方,而Web 服務器使用Session 數據時,也是從這個集中存儲Session 數據的地方來讀取。這樣的方式保證了不同Web 服務器上讀到的Session 數據都是一樣的。而存儲Session 數據的具體方式,可以使用數據庫,也可以使用其他分布式存儲系統。這個方案解決了SessionReplication 方案中內存的問題,而對於網絡帶寬,這個方案也比Session Replication 要好。該方案存在的問題是什么呢?

讀寫Session 數據引入了網絡操作,這相對於本機的數據讀取來說,問題就在於存在時延和不穩定性,不過我們的通信基本都是發生在內網,問題不大。

如果集中存儲Session 的機器或者集群有問題,就會影響我們的應用。

相對於Session Replication,當Web 服務器數量比較大、Session 數比較多的時候,這個集中存儲方案的優勢是非常明顯的。

4.Cookie Based

Cookie Based 方案是要介紹的最后一個解決Session 問題的方案。這個方案對於同一個會話的不同請求也是不限制具體處理機器的。和Session Replication 以及Session 數據集中管理的方案不同,這個方案是通過Cookie 來傳遞Session 數據的。還是先看看下面的圖2-13吧。

從圖2-13 可以看到,我們的Session 數據放在Cookie 中,然后在Web 服務器上從Cookie中生成對應的Session 數據。這就好比我每次都把自己的碗筷帶在身上,這樣我去哪家飯店吃飯就可以隨意選擇了。相對於前面的集中存儲,這個方案不會依賴外部的一個存儲系統,也就不存在從外部系統獲取、寫入Session 數據的網絡時延、不穩定性了。不過,這個方案依然存在不足:

Cookie 長度的限制。我們知道Cookie 是有長度限制的,而這也會限制Session 數據的長度。

安全性。Session 數據本來都是服務端數據,而這個方案是讓這些服務端數據到了外部網絡及客戶端,因此存在安全性上的問題。我們可以對寫入Cookie 的Session 數據做加密,不過對於安全來說,物理上不能接觸才是安全的。

帶寬消耗。這里指的不是內部Web 服務器之間的帶寬消耗,而是我們數據中心的整體外部帶寬的消耗。

性能影響。每次HTTP 請求和響應都帶有Session 數據,對Web 服務器來說,在同樣的處理情況下,響應的結果輸出越少,支持的並發請求就會越多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM