JAVA基礎--session共享的前生今世

session共享的前生今世

Session及cookie基本概念及生命週期

  • session

  當瀏覽器發起一個新的HTTP請求時,WEB服務端會主動創建一個session.並分配一個sessionID作爲服務端識別客戶端的一個標識,session對象會保存在服務端.此時session對象處於NEW STATE狀態,如果調用

session.isNew()

則返回true.當服務器處理完相應的請求時候,會將sessionID同reponse響應消息 一起傳回客戶端瀏覽器,並將其存到該客戶端瀏覽器的cookie中。當客戶端再發送其它http請求的時候.會將sessionID連同request消息一起發送給服務端。服務端再根據傳過來的sessionID將這次request與保存在服務端的session對象聯繫起來.此時的session對象已不是NEWSTATE狀態.這樣循環多次.直到session對象超時或銷燬.

注:當客戶端瀏覽器禁用cookie時,sessionID將不能保存在cookie中,一般此種情況,會使用url重寫,將sessionID作爲請求參數來進行客戶端和瀏覽器的信息傳輸交互

  • cookie   cookie是在客戶端保存一些少量數據的解決方案.而session是在服務端保存少量數據的方案. 如果cookie不設定時間的話就表視它的生命週期爲瀏覽器會話的期間,只要關閉瀏覽器,cookie就消失了,這種cookie被稱爲會話cookie.其一般不保存在硬盤上.而是保存在內存中。如果設置了過期時間.那麼瀏覽器會把cookie保存到硬盤中,再次打瀏覽器時會依然有效.直到它的有效期超時;

注:會話cookie可以在一個瀏覽器間的不同的tab頁中共享。隨瀏覽器主進程的關閉而失效 存儲在硬盤中的cookie可以在不同瀏覽器進程間共享。

分佈式系統session共享問題的由來

  目前大多數大型web應用都採用了分佈式服務集羣的部署方式,所謂集羣,就是讓一組計算機服務器協同工作,解決大併發,高可用,水平擴展的問題。但是在服務集羣中,session共享往往是一個比較頭疼的問題。因爲session是在服務器端保存的,如果用戶跳轉到其他物理服務器的話,session就會丟失,一般情況下,session對象在後端是不可跨物理服務器而存在。於是就有了分佈式系統的session共享問題。 目前公司有很多的應用都是集羣佈置環境,但是,有很多項目運維在配置f5作負載均衡時,作了訪問地址ip hash算法來分擔流量,該算法根據訪問客戶端的IP地址進行歸類並和集羣中的真實的服務器數取模,得到一個固定值,來分配真實的服務器,這樣的確可以分擔部分的流量,但並沒有起到failover的功能,即這臺服務器掛機後,該客戶端的請求信息仍然會發送到該服務器上,並且,如果服務器集羣中,真實的服務器有硬件性能上的差異,在這種分配策略上也做不到所謂的“能者多勞”。所以,要做到真正的HA,這種算法是不合適的。

所以,爲了提高程序的HA及提供failover,在應用端如果是集羣佈置,並且在應用的開發過程中,如果在session中保存了相關的內容,則最好要提供分佈式的session解決方案。

常用的集羣Session共享的方式

  • 客戶端Cookie保存方案,將原來保存在session中的內容以加密的方式保存在客戶端cookie中。
  1. 優點:減輕服務器端的壓力,每次session信息被寫回客服端,然後經瀏覽器再次提交到服務器。即使兩次請求即使在集羣中的不同服務器上完成,由於session信息都是隨請求信息一起提交,也可以到達session共享。
  2. 缺點:
    1. 傳遞cookie時,http信息頭的長度限制使我們只能夠在cookie中存入少量的用戶信息;
    2. 需要額外地做session信息加密的工作;
    3. 如果採用這種方式,每次訪問網站二級域名時都會在http信息頭中帶有這些以cookie形式存儲的值信息,會佔用一定的帶寬;
    4. 信息存儲是在客戶端進行,用戶完全可以禁用cookie或刪除cookie,不是很可靠
  • 服務器間Session同步方案,將session對象在集羣中的所有物理機上作同步 服務器間session同步策略,不同的容器有不同的解決方案。一般常用以下2種
  1. 使用主-從服務器的架構,當用戶在主服務器上登錄後,通過腳本或者守護進程的方式,將session信息傳遞到各個從服務器中,這樣,用戶訪問其它的從服務器時,就可以讀到session信息。 缺點:比如速度慢、不穩定等,另外,如果session信息傳遞是主->從單向的,會有一些風險,比如主服務器down了,其它服務器無法獲得session信息
  2. Session 對象的集羣中的廣播機制。 一臺主機中產生session中,將此session對象在集羣網絡中進行廣播同步,各集羣中的主機收到廣播後,再同步到本地的session內存域中。 缺點:如果session內容中有大型對象時,不適合傳輸。集羣範圍中網絡中對存在大量的廣播消息,佔用帶寬,會有延時.
  • 使用集中統一管理Session方案 即將集羣中各主機產生的session對象都存儲到一箇中心存儲結構中,目前比較流行的存儲結構是:redis集羣,Memcache,mysql數據庫等。這種集中存儲的結構,能斛決上面方案中的一些弊斷。但也有一些應用上問題。比如選擇mysql作存儲結構中,mysql數據庫可以用作存儲的session對象,但在併發量高時,對數據庫的讀寫要求較高,還需要另外提高session失效的相關算法。Redis集羣,memcache主要是以內存爲存儲介質,有先天的讀寫優勢,並且都能提供失效機制,特別適合用來作session的存儲結構。所以,這一種比較好的解決方案。   目前這兩種方案都有容器插件的方式部署在容器中有解決方案,但有其相應的缺點:
  1. 插件的版本更新不及時。
  2. 對容器不透明,不同容器要適配不同的插件。
  3. 插件本身的穩定性無法控制。
  4. 運維在配置集羣時,還要特別注意相關插件的配置。增加了維護的難度。

相應的優點就是:對程序透明,開發程序時候,不用考慮集羣,還是單機環境。佈置簡單,沒有額外的工作量。

Spring Session的使用方式

第一步:引入依賴,根據需要配置相應的存儲
<dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session-data-redis</artifactId>
     <version>1.3.1.RELEASE</version>
     <type>pom</type>
     <exclusions>
         <exclusion>
             <groupId>org.springframework.data</groupId>
             <artifactId>spring-data-redis</artifactId>
         </exclusion>
         <exclusion>
             <groupId>redis.clients</groupId>
             <artifactId>jedis</artifactId>
         </exclusion>
     </exclusions>
 </dependency>
第二步:web應該配置filter過濾器。
<filter>
   <filter-name>springSession</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
   <filter-name>springSession</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
第三步:配置相應的SPRING BEAN
<bean id="springSession" class="org.springframework.session.web.http.SessionRepositoryFilter"
     c:sessionRepository-ref="redisOperationsSessionRepository" p:httpSessionStrategy-ref="cookieHttpSessionStrategy" />
<bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer"
     p:cookiePath="/" />
<bean id="cookieHttpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy"
     p:cookieSerializer-ref="defaultCookieSerializer" />
<bean name="redisOperationsSessionRepository" class="org.springframework.session.data.redis.RedisOperationsSessionRepository"
     c:redisConnectionFactory-ref="connectionFactory" p:defaultMaxInactiveInterval="${session.timeout}" />
  • 使用spring session的優點
  1. 統一項目中對session共享問題的處理方案。
  2. 降低運維複雜度,使解決方案和容器解耦。
  3. 構建統一的session存儲redis環境,不需要每個項目都自行構建一套session的存儲介質。公司正式環境也可以構建統一的,HA,FAILOVER的session存儲環境。逐步降低一個應用佔用物理服務器超配的現象。
  • 缺點
  1. Spring session解決方案是spring社區新的子項目,面世時間不長,目前1.3版本。有集成穩定性,及集成兼容性的風險。特別是公司裏一些老的系統,由於jdk,spring的版本都較低,是不是適合上,要綜合評估。
  2. 集成對應用有一定的調整工作量。
  • 存儲樣式 127.0.0.1:6379> keys *
  • 1) “spring:session:expirations:1235654675878”
  • 2) “spring:session:sessions:fdf-d1e4-44b3-a83a-FDSA”
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章