1. 程式人生 > >集群中的session共享問題解決方案

集群中的session共享問題解決方案

session復制 宕機 active log tab 三方 ase target redis

一. 大致說一下nginx的負載均衡策略

1.輪詢(默認):

每個請求按時間順序逐一分配到不同的後端服務器,如果後端某臺服務器宕機,則自動剔除故障機器,使用戶訪問不受影響。

2.weight:

指定輪詢權重,weight值越大,分配到的幾率就越高,主要用於後端每臺服務器性能不均衡的情況。

3.ip_hash:

每個請求按訪問IP的哈希結果分配,這樣每個訪客固定訪問一個後端服務器,可以有效的解決動態網頁存在的session共享問題。(此為解決session共享的一種方式)

4.fair(第三方):

更智能的一個負載均衡算法,此算法可以根據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間來分配請求,響應時間短的優先分配。如果想要使用此調度算法,需要Nginx的upstream_fair模塊。

5.url_hash(第三方):

按訪問URL的哈希結果來分配請求,使每個URL定向到同一臺後端服務器,可以進一步提高後端緩存服務器的效率。如果想要使用此調度算法,需要Nginx的hash軟件包。

二. 解決session共享問題常用的三種方式

1. nginx配置ip_hash為負載均衡策略即可解決session共享問題。

思路:因為ip_hash策略的結果是同一ip會訪問同一臺服務器,實際上session並沒有共享,只是因為同一IP會一直訪問一臺服務器,自然不存在共享的問題。那麽可想而知,換個IP,session並沒有共享。

  技術分享圖片

nginx配置示例:

upstream test{
ip_hash;
server 192.168.10.13:80;
server 192.168.10.15:8009  max_fails=3  fail_timeout=20s;
}
server {
  location / {
    proxy_pass  http://test;
  }
}

2. 服務器之間session復制(tomcat)

思路:直接讓在集群中的服務器中都復制一份session唄,那麽不管反代采用的是負載均衡策略,都不會出現session丟失的問題。

  技術分享圖片

tomcat配置為如下兩個步驟:

① 修改server.xml中的Cluster節點

② 修改應用的web.xml,增加節點: <distributable/>

兩步實際上用的是tomcat自帶的集群。

配置示例:

http://blog.csdn.net/wlwlwlwl015/article/details/48160433

這篇寫的不錯。

3. session統一緩存

思路:用redis統一緩存session,我們的應用需要連接到redis,用redis裏的session就好了。下面是使用filter的原理。

(配置context.xml也可以,可以看下 https://lanjingling.github.io/2015/12/15/tomcat-redis-session/ 或者 https://www.jianshu.com/p/aa9f71d653af)

  技術分享圖片

優缺點

  技術分享圖片

配置步驟:

① 增加redis client和spring session的依賴(pom.xml)

<dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.1</version>
</dependency>

② 修改web.xml,增加filter,註意:這個filter必須寫到最前面

技術分享圖片

③ 修改Spring配置文件,在容器中註入spring session和redis相關的bean。

    <bean id="redisHttpSessionConfiguration"
        class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="maxInactiveIntervalInSeconds" value="600" />
    </bean>
 
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="100" />
        <property name="maxIdle" value="10" />
    </bean>
 
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        destroy-method="destroy">
        <property name="hostName" value="localhost" />
        <property name="port" value="6379" />
        <property name="timeout" value="3000" />
        <property name="usePool" value="true" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>

需要註意的地方:

  技術分享圖片

三. 三種應用的場景

  技術分享圖片

  

集群中的session共享問題解決方案