集群session管理問題

2022-07-29 17:24:23 字數 4133 閱讀 7741

**:

先來看一下什麼是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 伺服器來說,在同樣的處理情況下,響應的結果輸出越少,支援的併發請求就會越多。

集群的session管理

1.session複製。集群之前相互複製session資料。在集群小時沒問題,集群數量機器多時,集群伺服器之間需要大量的通訊進行session複製,占用伺服器和網路的大量資源,系統不堪重負。在大量使用者訪問情況下,伺服器記憶體會不夠用。並且每台伺服器的session資料都是一樣的,實際上也是在浪費記...

集群session問題(一)

這個方案比較簡單 再負載均衡器上將同樣的session請求發往同乙個伺服器,其實還是相當於單機,只是在負載均衡器上做處理了。這樣的好處就是 簡單 缺點如下 1 如果有一台web伺服器宕機,那麼這台機器上的會話資料全丟失,使用者需要重新登入 2 會話標識是應用層的資訊,那麼負載均衡器要將同乙個會話請求...

解決Redis管理集群下Session丟失問題

在集群環境下,session會有丟失的問題 解決 session複製 session replication 記憶體的浪費 ip繫結 a.有可能負載不均衡 b.也有可能session資料丟失 通過cookie管理session a.cookie客戶端行為 b.中文單獨處理 通過redis管理集群下的...