轉 解決應用服務器變爲集羣后的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 服務器來講,在一樣的處理狀況下,響應的結果輸出越少,支持的併發請求就會越多。

相關文章
相關標籤/搜索