解決session共享問題方式調研

爲了提高服務器性能,最近公司項目採用了分佈式服務集羣的部署方式。所謂集羣,就是讓一組計算機服務器協同工作,解決大併發,大數據量瓶頸問題。項目使用nginx做負載均衡,這樣同一個IP訪問同一個頁面會被分配到不同的服務器上,此時就涉及到一個session共享的問題。因爲session是在服務器端保存的,如果用戶跳轉到其他服務器的話,session就會丟失,一般情況下,session不可跨服務器而存在。於是就有了分佈式系統的session共享問題。

集羣中session安全和同步是個最大的問題,下面是收集到的幾種session同步的方案,希望能通過分析其各自的優劣找出其適應的場景。

一、客戶端cookie加密

當用戶登陸成功以後,把網站域名、用戶名、密碼、token、 session有效時間全部採用cookie的形式寫入到客戶端的cookie裏面。如果用戶從一臺Web服務器跨越到另一臺服務器的時候,我們的程序主動去檢測客戶端的cookie信息,進行判斷,然後提供對應的服務,當然,如果cookie過期,或者無效,自然就不讓用戶繼續服務了。

優點:

簡單、高效,也不會加大數據庫的負擔。

缺點:

  1. cookie安全性較低,雖然它已經加了密,但是還是可以僞造的。
  2. 但是如果客戶端把cookie禁掉了的話,那麼session就無從同步了,這樣會給網站帶來損失;
  3. session中數據不能太多,最好只有個用戶id。

二、session複製

大部分應用服務器都提供了session複製的功能來實現集羣,tomcat,jboss,was都提供了這樣的功能。

優點:

通過應用服務器配置即可,無需改動代碼。

缺點:

  1. 性能隨着服務器增加急劇下降,而且容易引起廣播風暴;
  2. session數據需要序列化,影響性能。

三、使用數據庫保存session

這種共享session的方式即將session信息存入數據庫中,其它應用可以從數據庫中查出session信息。

優點:

使用數據庫來保存session,就算服務器宕機了也沒事,session照樣在。

缺點:

  1. 每次請求都需要對數據庫進行讀寫,session的併發讀寫在數據庫中完成,會加大數據庫的IO,對數據庫性能要求比較高。
  2. 我們需要額外地實現session淘汰邏輯代碼,即定時從數據庫表中更新和刪除session信息,增加了工作量。
  3. 數據庫讀寫速度較慢,不利於session的適時同步。

四、使用redis或memcache來保存session

提供一個集羣保存session共享信息,其他應用統統把自己的session信息存放到session集羣服務器組。當應用系統需要session信息的時候直接到session羣集服務器上讀取。目前大多都是使用Memcache或redis來對Session進行存儲。以這種方式來同步session,不會加大數據庫的負擔,並且安全性比用cookie大大的提高,把session放到內存裏面,比從文件中讀取要快很多。
以redis來實現Session共享的方式目前比較流行的有兩種實現方案,下面主要對這兩種方案進行介紹。

1. tomcat-cluster-redis-session-manager

使用 tomcat-redis-session-manager 開源項目解決分佈式session跨域的問題,他的主要思想是利用Servlet容器提供的插件功能,自定義HttpSession的創建和管理策略,並通過配置的方式替換掉默認的策略。tomcat-redis-session-manager重寫了Tomcat的org.apache.catalina.session.ManagerBase裏邊的具體寫的操作, 將tomcat的session存儲位置指向了Redis:

RedisSessionManager 繼承了org.apache.catalina.session.ManagerBase並重寫了 addfindSessioncreateEmptySessionremove 等方法,並將對session 的增刪改查操作指向了對Redis數據存儲的操作。

具體可以參考:Redis+Tomcat+Nginx集羣實現Session共享,Tomcat Session共享

優點:

無需修改任何代碼。

缺點:

  1. 配置相對還是有一點繁瑣,需要人爲的去修改Tomcat的配置。
  2. 暫時此插件只支持tomcat7、tomcat8、tomcat9,對於tomcat有較大的依賴。

2. 使用Spring Session和redis管理session

Spring Session不依賴於Servlet容器,而是Web應用代碼層面的實現,直接在已有項目基礎上加入spring Session框架來實現Session統一存儲在Redis中。如果你的Web應用是基於Spring框架開發的,只需要對現有項目進行少量配置,即可將一個單機版的Web應用改爲一個分佈式應用,由於不基於Servlet容器,所以可以隨意將項目移植到其他容器。

優點:

  1. 如果web應用是基於spring框架開發的,那麼只需簡單配置,既可以修改爲一個分佈式應用。
  2. 不急於servlet容器,可以隨意將項目移植到其他容器。

缺點:

需要修改代碼。

具體可以參考:使用Spring Session和Redis解決分佈式Session跨域共享問題


參考鏈接:

解決nginx負載均衡的session共享問題

java集羣之session共享解決方案

發佈了77 篇原創文章 · 獲贊 62 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章