我們實現的方案可以說是第二種方案和第三種方案的合體,可以利用gemfire實現session複製共享,還可以將session維護在redis中實現session共享,同時可以將session維護在客戶端的cookie中,但是前提是資料要加密。這三種方式可以迅速切換,而不影響應用正常執行。我們在實踐中,首選gemfire或者redis作為session共享的載體,一旦session不穩定出現問題的時候,可以緊急切換cookie維護session作為備用,不影響應用提供服務,下面我簡單介紹方案中session共享的實現方式和原理。
這裡主要講解redis和cookie方案,gemfire比較複雜大家可以自行檢視gemfire工作原理。利用redis做session共享,首先需要與業務邏輯**解耦,不然session共享將沒有意義,其次支援動態切換到客戶端cookie模式。redis的方案是,重寫伺服器中的httpsession和httpservletrequest,首先實現httpsession介面,重寫session的所有方法,將session以hash值的方式存在redis中,乙個session的key就是sessionid,setatrribute重寫之後就是更新redis中的資料,getattribute重寫之後就是獲取redis中的資料,等等需要將httpsession的介面一一實現。
實現了httpsesson,那麼我們先將該session類叫做mysession(當然實踐中不是這麼命名的),當mysession出現之後問題才開始,怎麼能在不影響業務邏輯**的情況下,還能讓原本的request.getsession()獲取到的是mysession,而不是伺服器原生的session。這裡,我決定重寫伺服器的httpservletrequet,這裡先稱為myrequest,但是這可不是單純的重寫,我需要在原生的request基礎上重寫,於是我決定在filter中,實現request的偷梁換柱,我的思路是這樣的,myrequest的構建器,必須以request作為引數,於是我在filter中將伺服器原生的request(也有可能是框架封裝過的request),當做引數new出來乙個myrequest,並且myrequest也實現了httpservletrequest介面,其實就是對原生request的乙個增強,這裡主要重寫了幾個request的方法,但是最重要的是重寫了request.getsession(),寫到這裡大家應該都明白為什麼重寫這個方法了吧,當然是為了獲取mysession,於是這樣就在filter中,偷偷的將原生的request換成myrequest了,然後再將替換過的request傳入chan.dofilter(),這樣filter時候的**都使用的是myrequest了,同時對業務**是透明的,業務**獲取session的方法仍然是request.getsession(),但其實獲取到的已經是mysession了,這樣對session的操作已經變成了對redis的操作。這樣實現的好處有兩個,第一開發人員不需要對session共享做任何關注,session共享對使用者是透明的;第二,filter是可配置的,通過filter的方式可以將session共享做成一項可插拔的功能,沒有任何侵入性。
這個時候已經實現了一套可插拔的session共享的框架了,但是我們想到如果redis服務出了問題,這時我們該怎麼辦呢,於是我們延續redis的想法,想到可以將session維護在客戶端內(加密的cookie),當然實現方法還是一樣的,我們重寫httpsession介面,實現其所有方法,比如setattribute就是寫入cookie,getattribute就是讀取cookie,我們可以將重寫的session稱作mysession2,這時怎麼讓開發人員透明的獲取到mysession2呢,實現方法還是在filter內偷梁換柱,在myrequest加乙個判斷,讀取sessiontype配置,如果sessiontype是redis的,那麼getsession的時候獲取到的是mysession,如果sessiontype是coolie的,那麼getsession的時候獲取到的是mysession2,以此類推,用同樣的方法就可以獲取到mysession 3,4,5,6等等。
這樣兩種方式都有了,那麼我們怎實現兩種session共享方式的快速切換呢,剛剛我提到乙個sessiontype,這是用來決定獲取到session的型別的,只要變換sessiontype就能實現兩種session共享方式的切換,但是sessiontype必須對所有的伺服器都是一致的,如果不一致那將會出現比較嚴重的問題,我們目前是將sessiontype維護在環境變數裡,如果要切換sessiontype就要重啟每一台伺服器,完成session共享的轉換,但是當伺服器太多的時候將是一種災難。而且重啟服務意味著服務的中斷,所以這樣的方式只適合伺服器規模比較小,而且使用者量比較少的情況,當伺服器太多的時候,務必需要一種協調技術,能夠讓伺服器能夠及時獲取切換的通知。基於這樣的原因,我們選用zookeeper作為配置平台,每一台伺服器都會訂閱zookeeper上的配置,當我們切換sessiontype之後,所有伺服器都會訂閱到修改之後的配置,那麼切換就會立即生效,當然可能會有短暫的時間延遲,但這是可以接受的。
方案大體分享完了,在此將我的收穫記錄下來,我們已經實現了乙個版本,大家也可以發揮想象,分享不同的方案,我們一起進步,文中有不足之處,還望各位不吝賜教。
演算法導論 第三版英文版》_高畫質中文版.pdf
《深度學習入門:基於python的理論與實現》_高畫質中文版.pdf
《深入淺出資料分析》_高畫質中文版.pdf
《python程式設計:從入門到實踐》_高畫質中文版.pdf
《python科學計算》_高畫質中文版.pdf
分布式Session的實現
一 session複製,專業名詞叫session replication 二 session 粘性,主頁名詞叫session sticky 三 快取集中式管理 簡介 將session存入分布式快取集群中的某台機器上,當使用者訪問不同節點時先從快取中拿session資訊 這個是主流的實現方式,最大的缺...
Redis實現分布式Session
對於多web的環境現在已經是必須的了,很難想像一台web伺服器面對百萬併發的響應,所以,我們需要多台web伺服器集群合作,來緩解這種高併發,高吞吐的場景,而對於多web的場景又會有個問題出現,即session儲存的問題,如乙個使用者登陸後,把乙個狀態資訊儲存到當前web伺服器的session裡,而你...
分布式session共享
為什麼會出現session共享問題?客戶端與伺服器互動時會產生唯一的sessionid用於標記使用者,但是在分布式架構中,如果還是採用 session 的方式,使用者發起請求,通過 nginx 做請求 時,並不知道是 到伺服器1還是伺服器2,所以就會出現session共享問題。今天主要記錄使用 sp...