集群中的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>

需要注意的地方:

  

三.  三种应用的场景

  

  

原文地址:https://www.cnblogs.com/NoYone/p/8604406.html