1. 程式人生 > >網際網路分散式系統Session一致性問題解析

網際網路分散式系統Session一致性問題解析

1. 什麼是Session?

使用者使用網站的服務,需要使用瀏覽器與Web伺服器進行多次互動。HTTP協議本身是無狀態的,需要基於HTTP協議支援會話狀態(Session State)的機制。具體的實現方式是:在會話開始時,分配一個 

唯一的會話標識(SessionID),並通過Cookie將這個標識告訴瀏覽器,以後每次請求的時候,瀏覽器都會帶上這個會話標識SessionID來告訴Web伺服器這個請求是屬於哪個會話的。在Web伺服器上,各個會話都有獨立的儲存,儲存不同會話的資訊。如果遇到禁用Cookie的情況,一般的做法就是把這個會話標識放到URL的引數中。

當Web伺服器從一臺變為多臺時,就會出現Session一致性問題。

如上圖所示,當一個帶有會話標識的HTTP請求到了Web伺服器後,需要在HTTP請求的處理過程中找到對應的會話資料(Session)。但是,現在存在的問題就是:如果我第一次訪問網站時請求落到了左邊的伺服器,那麼我的Session就建立在左邊的伺服器上了,如果我們不做處理,就不能保證接下來的請求每次都落在同一邊的伺服器上了。這就是Session一致性問題。

在單機的情況下,會話儲存在單機上,請求也是由這個機器處理,因此不會有問題。當Web伺服器變為多臺以後,如果保證同一個會話的請求都在同一個Web伺服器上處理,則對該會話來說,與之前單機的情況是一樣的。

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

方式。

該方案本身非常簡單,對於Web伺服器來說,該方案和單機的情況是一樣的,只是我們在負載均衡器上做了手腳。這個方案可以讓同樣Session的請求每次都發送到同一個Web伺服器來處理,非常利於針對Session進行服務端本地的快取。

其所存在的問題包括:

如果有一臺Web伺服器宕機或者重啟,則該機器上的會話資料就會丟失。如果會話中有登入狀態資料,則使用者需要重新登陸。

會話標識是應用層的資訊,則負載均衡器要將同一個會話的請求都儲存到同一個Web伺服器上的話,就需要進行應用層(七層)的解析,這個開銷比第四層的交換要大。

負載均衡器變為了一個有狀態的節點,要將會話儲存到具體Web伺服器的對映,因此記憶體消耗會更大,容災會更麻煩。

打個比方來說,對於Session Stiky,如果說Web伺服器是我們每次吃飯的飯店,會話資料就是我們吃飯用的碗筷。要保證每次吃飯都用自己的碗筷,我就把餐具存在某一家,並且每次都去這家店吃,這是個不錯的主意。

如果我們繼續以去飯店吃飯類比,那麼除了前面的方式之外,如果我在每個店都存放一套自己的餐具,就可以更加自由地選擇飯店。Session Replication就是這樣一種方式,如下圖所示。

可以看到,在Session Replication方案中,不再要求負載均衡器來保證同一個會話地多次請求必須到同一個Web伺服器上了。而我們的Web伺服器之間則增加了會話資料的同步。通過同步就保證了不同Web伺服器之間的Session資料的一致。

但是,Session Replication方案也存在一些問題,包括:

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

每臺Web伺服器都要儲存所有的Session資料,如果整個叢集的Session數很多的話,每臺機器用於儲存Session資料的內容佔用會很嚴重。

這就是Session Replication方案。這個方案是靠應用容器來完成Session的複製從而使得應用解決Session問題的,應用本身並不關心這個事情。不過,這個方案並不適合叢集機器數多的場景。如果只有幾臺機器,用該方案是可以的。

 session資料集中儲存

思路:將session儲存在web-server後端的儲存層,資料庫或者快取

優點

沒有安全隱患

可以水平擴充套件,資料庫/快取水平切分即可

web-server重啟或者擴容都不會有session丟失

不足:增加了一次網路呼叫,並且需要修改應用程式碼

對於db儲存還是cache,個人推薦後者:session讀取的頻率會很高,資料庫壓力會比較大。如果有session高可用需求,cache可以做高可用,但大部分情況下session可以丟失,一般也不需要考慮高可用。

總結

保證session一致性的架構設計常見方法:

session同步法:多臺web-server相互同步資料

客戶端儲存法:一個使用者只儲存自己的資料

反向代理hash一致性:四層hash和七層hash都可以做,保證一個使用者的請求落在一臺web-server上

後端統一儲存:web-server重啟和擴容,session也不會丟失

如何一起學習,有沒有免費資料?

在程式設計師這條路上遇到瓶頸的朋友可以加WX:daxigua012 大家一起來提升進步 但要備註“555” ,贈送一些Dubbo、Redis、Netty、zookeeper、Spring cloud、分散式資料