集群中的session共享問題解決方案
一. 大致說一下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共享問題解決方案