架構文摘:分散式系統Session一致性問題解析

KiteRunner24發表於2018-03-20

一、問題的提出

1. 什麼是Session?

使用者使用網站的服務,需要使用瀏覽器與Web伺服器進行多次互動。HTTP協議本身是無狀態的,需要基於HTTP協議支援會話狀態(Session State)的機制。具體的實現方式是:在會話開始時,分配一個
唯一的會話標識(SessionID),並通過Cookie將這個標識告訴瀏覽器,以後每次請求的時候,瀏覽器都會帶上這個會話標識SessionID來告訴Web伺服器這個請求是屬於哪個會話的。在Web伺服器上,各個會話都有獨立的儲存,儲存不同會話的資訊。如果遇到禁用Cookie的情況,一般的做法就是把這個會話標識放到URL的引數中。

2. 什麼是Session一致性問題?

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

架構文摘:分散式系統Session一致性問題解析

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

二、Session一致性解決方案

1. Session Stiky

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

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

架構文摘:分散式系統Session一致性問題解析

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

其所存在的問題包括:

  • 如果有一臺Web伺服器當機或者重啟,則該機器上的會話資料就會丟失。如果會話中有登入狀態資料,則使用者需要重新登陸。
  • 會話標識是應用層的資訊,則負載均衡器要將同一個會話的請求都儲存到同一個Web伺服器上的話,就需要進行應用層(七層)的解析,這個開銷比第四層的交換要大。
  • 負載均衡器變為了一個有狀態的節點,要將會話儲存到具體Web伺服器的對映,因此記憶體消耗會更大,容災會更麻煩。

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

2. Session Replication

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

架構文摘:分散式系統Session一致性問題解析

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

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

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

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

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

3. Session資料集中儲存

同樣是希望同一個會話的請求可以發到不同的Web伺服器上,前面的Session Replication是一種方案,還有一種方案就是把Session資料集中儲存起來,然後不同Web伺服器從同樣的地方來獲取Session。其大概的結構如下圖所示:

架構文摘:分散式系統Session一致性問題解析

可以看到,與Session Replication方案一樣的部分是,會話請求經過負載均衡器後,不會被固定在同樣的Web伺服器上。不同的地方是,Web伺服器之間沒有Session資料複製,並且Session資料也不是儲存在本機了,而是放在了另一個集中儲存的地方。這樣,無論是哪臺Web伺服器,也無論修改的是哪個Session的資料,最終的修改都發生在這個集中儲存的地方,而Web伺服器使用Session資料時,也是從這個集中儲存Session資料的地方來讀取。對於Session資料儲存的具體方式,可以使用資料庫,也可以使用其他分散式儲存系統。這個方案解決了Session Replication方案中記憶體的問題,而對於網路頻寬,該方案也比Session Replication要好。

不過,該方案仍存在一些問題,包括:

  • 讀寫Session資料引入了網路操作,這相對於本機的資料讀取來說,問題就在於存在時延和不穩定性,不過由於通訊基本發生在內網,問題不大。
  • 如果集中儲存Session的機器或者叢集存在問題,這就會影響我們的應用。

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

對於Cookie Based方案,它對同一個會話的不同請求也是不限制具體處理機器的。與Session Replication和Session資料集中管理的方案不同,這個方案是通過Cookie來傳遞Session資料的。具體如下圖所示。

架構文摘:分散式系統Session一致性問題解析

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

不過,該方案依然存在不足,包括:

  • Cookie長度限制。由於Cookie是有長度限制的,這也會限制Session資料的長度。
  • 安全性。Session資料本來都是伺服器端資料,而這個方案是讓這些服務端資料到了外部外部網路及客戶端,因此存在安全性的問題。
  • 頻寬消耗。這裡指的不是內部Web伺服器之間的頻寬的消耗,而是我們資料中心的整體外部貸款的消耗。
  • 效能消耗。每次HTTP請求和響應都帶有Session資料,對Web伺服器來說,在同樣的處理情況下,響應的結果輸出越少,支援的併發請求就會越多。

三、總結

綜合而言,上述所有方案都是解決session問題的方案,對於大型網站來說,Session Sticky和Session集中管理是比較好的方案。

相關文章