上週用了整整一周時間,搞了乙個分布式會話的東西。儘管到了最後沒有完成的很完美,有一點點小問題延誤了上線,不過這對我自己來說,已經非常滿足了。拿出來分享一下。
當今,單節點架構的專案是很容易當掉的。網路攻擊、競爭公司「不正當訪問」、使用者量的大幅度提公升以及快速迭代、產品不斷打補丁上線,這都對系統的架構提公升了很高的要求。為了更好的應付需求變化,也為了確保系統的穩定性。公司決定把這個分布式會話提上日程。由於我對此興趣比較濃,自然把這個任務搶先佔了下來。
之前的架構是如下這樣,**寫的再漂亮,多執行緒考慮的再仔細,也抗不住各種io瓶頸。單一節點的結構,無法使用複雜多變的顯示需求。
一周的研究,終於出了個雛形。我在網上找了很多資料,結果跟我想的差不多。這種事情,肯定有多種方式、多種方法實現,這是毋庸置疑的。
其實,使用tomcat做為web伺服器也是可以的,只不過tomcat處理靜態化的能力相比於apache、nginx、iis等,會差很多,所以幾乎沒有公司選擇它。當然,我們也可以直接使高階伺服器做**,直接由硬體在資料鏈路層做**,這種方式,比一般的軟體做**,效率會更高一層。
不過,我們公司不是土豪公司,多搞一台linux伺服器,還是申請了老長時間才批下來的。我們選擇的web伺服器也很傳統——nginx。先看架構結構圖:
這裡,快取伺服器選擇的是memcache,使用kmemcached作為快取的客戶端,當然,你也可以選擇其他的儲存結構來儲存session。比如 當今如日中公升的redis、或者其他的資料庫以及記憶體資料庫均可。我這裡選用memcache,是因為頭兒對memcache很熟悉,資料也很完備的原因。不過,我個人更加傾向於redis,不過時間有限,先搞上乙個再說。
我們都知道,網路應用,說到本質上,都是在面向http程式設計的。而http是無狀態的,那我們如何保持使用者狀態,維持使用者的會話過程呢?我們一般的處理都講客戶端的資訊儲存在cookie中,服務端的狀態資訊儲存在session,如user或者userid,我們需要將物件或者單一的userid屬性儲存在session,來維持使用者會話狀態。
而單一節點的結構,無法應對多頻度的系統上線和系統宕機。唯一的解決辦法,就是重啟伺服器。這一點的使用者體驗,是非常差的(一兩年前,就在csdn寫部落格的童鞋應該大有體會,看到維護中待解決的心情,不解釋。當然現在csdn是越來越好了~~嘻嘻~~)。
所以說,不僅人要懂得分工合作,系統更要分布。而問題的節點就在於session。所以我們把session從服務端拿出來,將session儲存在記憶體資料庫中,也就是說將user資訊,儲存在記憶體資料庫中,多個tomcat伺服器的會話狀態,由記憶體資料庫統一維護。這樣就能夠將系統進行分布部署。
使用nginx做web伺服器,它能夠處理靜態資源,將js、css、等靜態資源過濾出來,直接傳送給客戶端,而將動態請求,根據一定的策略、權重,動態分發到不同的伺服器上,分攤伺服器壓力。
那麼,我們如何將session儲存在記憶體資料庫中呢?直接在**中改嗎?很大的工作量啊。我這裡使用的是新增乙個sessionfilter,注意,這個filter,一定要在所有含狀態請求的前面,也就是說,這個filter,做好放在所有filter的上面。因為filter的執行順序是根據filter的位置,像棧一樣執行的。如filter1在filter2之上,執行順序就是:filter1>filter2>程式》filter2>filter1.
在這個sessionfilter中,重新包裝request,所有對session的增刪改查操作,都需要涉及到cookie、memcache庫中的session資訊的狀態。
這裡只講乙個思路,感興趣的童鞋,可以跟我發郵件交流。
搞這個過程中,遇到的問題:
1、filter管理的問題。一般我們會在web.xml裡面標籤裡面,直接filter的類路徑,這時,filter在初始化時直接由容器管理,初始化到記憶體中了。沒什麼說的,如果我們希望交給spring管理,那麼我們必須把寫成
org.springframework.security.util.filtertobeanproxy,這時,我們可以通過配置,將filter初始化到某個bean中。
2、改造sessionfilter,sessionfilter是分布式會話的核心。它的每次修改,都需要重新編譯,重啟服務。封裝session的setattribute方法時,沒有考慮session.setattribute("user",null)的情況,因為所有傳遞的物件都需要序列化,而null不是序列化物件,當然會失敗。
3、memcache快取策略尚待考慮。
4、nginx配置+https配置。
5、伺服器端防火牆等的配置。
登入模組 分布式會話設計文件
session複製 session繫結 spring security集中式會話的設計 會話保持 我們都知道http是無狀態協議,如果我們在同一 進行連續兩次請求時,伺服器是無法識別兩次請求的相關性,尤其是需要登入認證的 如果第乙個請求是登入請求,伺服器認證成功,然後進行第二次請求,服務端仍然無法識...
分布式 分布式鎖
本質是利用redis的setnx 方法的特性來加鎖,setnx 即key不存在則設定key,否則直接返回false,要求在分布式系統中使用同乙個redis服務,以下提供兩種解決方案 1 直接使用redistemplate 這其實並不能完全保證高併發下的安全問題,因為可能在鎖過期之後該執行緒尚未執行完...
分布式 分布式事務
是資料庫執行過程中的乙個邏輯單位,由乙個有限的資料庫操作序列構成。事務的acid四大特性 原子性 atomicity 事務作為乙個整體被執行。一致性 consistency 從乙個一致的狀態轉換到另乙個一致的狀態。隔離性 isolation 多個事務併發執行時,併發事務之間互相影響的程度。永續性 d...