分布式中解决session共享方案

分布式中解决session共享方案

1. nginx方案

nginx提供了ip_hash策略,可以保持用户ip进行hash值计算固定分配到某台服务器上,然后只要是该ip则会保持分配到该服务器上,保证用户访问的是同一台服务器,那么session问题就不存在了。这也是解决session共享的一种方式,也称为黏性session。但是假设一台tomcat服务器挂了的话,那么session也会丢失。所以比较好的方案是抽取session。
在这里插入图片描述

2. tomcat方案

tomcat与redis集成实现session共享:
环境为tomcat7 + jdk1.6的话:
在所有需要共享session的服务器的tomcat中目录下:
lib目录中添加以下三个jar包,注意版本最好一致,不然极容易出现错误,下边的测试是可用的:
在这里插入图片描述
conf目录中content.xml中加入:配置redis服务
在这里插入图片描述
环境为tomcat7 + jdk1.7或1.8的话:
在所有需要共享session的服务器的tomcat中目录下:
lib目录中添加以下三个jar包,测试通过:
在这里插入图片描述
conf目录中content.xml中加入:配置redis服务
在这里插入图片描述
根据我这测试,是jkd1.8+tomcat7,在137和139两台tomcat中加入jar包且进行如上配置:
在这里插入图片描述
修改content.xml
在这里插入图片描述

添加两个注意点

1、按照如上配置,使用redis数据库,放入session中的对象必须要实现java.io.Serializable接口,使用memcache的可以不用实现Serializable接口
原因是:因为tomcat里使用的将session放置redis使用的工具类,是使用的jdk序列化模式存储的,这一点也是很容易理解的,session.setAttribute(String key, Object value),存储Object类型
object放入redis中又要能取出来,只能是序列化进行存储了,然后取出的时候进行反序列化。
所以我们在session中存储的任何对象,都必须实现序列化接口。
2、按照如上配置,使用redis做session存储空间时,web应用的session-time的时间单位会变成[秒],而不是原本的[分]
原因是:因为tomcat里使用的将session放置redis使用的工具类,在存储时为对tomcat容器时间做转换
在redis中设置过期时间是使用秒作为单位的,有个命令叫expire可以设置redis键值过期时间,所以在context.xml配置文件中我们需要制定session过期时间(默认是60秒,配成1800即30分钟),这一点很重要。
请注意!!!!
context.xml配置说明:
在这里插入图片描述
3.Spring Session+Spring Data Redis 解决
(1)引入相关jar包:
这里需要引入Spring Session和Spring Data Redis相关的依赖jar包。可以自行从maven仓库下载,也可以参考使用的jar包:down.51cto.com/data/228183…
(2)修改spring-data-redis相关配置:
在项目的spring-data-redis相关配置中添加以下配置:




完整的context_redis_cluster.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>


spring-data-redis-cluster

<!-- 配置Cluster -->
<bean id="redisClusterConfiguration"
    class="org.springframework.data.redis.connection.RedisClusterConfiguration">
    <property name="maxRedirects" value="${redis.cluster.maxRedirects}" />
    <!-- 节点配置 -->
    <property name="clusterNodes">
        <set>
            <bean class="org.springframework.data.redis.connection.RedisClusterNode">
                <constructor-arg name="host" value="${redis.cluster.host1}" />
                <constructor-arg name="port" value="${redis.cluster.port1}" />
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisClusterNode">
                <constructor-arg name="host" value="${redis.cluster.host2}" />
                <constructor-arg name="port" value="${redis.cluster.port2}" />
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisClusterNode">
                <constructor-arg name="host" value="${redis.cluster.host3}" />
                <constructor-arg name="port" value="${redis.cluster.port3}" />
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisClusterNode">
                <constructor-arg name="host" value="${redis.cluster.host4}" />
                <constructor-arg name="port" value="${redis.cluster.port4}" />
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisClusterNode">
                <constructor-arg name="host" value="${redis.cluster.host5}" />
                <constructor-arg name="port" value="${redis.cluster.port5}" />
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisClusterNode">
                <constructor-arg name="host" value="${redis.cluster.host6}" />
                <constructor-arg name="port" value="${redis.cluster.port6}" />
            </bean>
        </set>
    </property>
</bean>

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxTotal" value="${redis.cluster.jedisPoolConfig.maxTotal}" />
    <property name="maxIdle" value="${redis.cluster.jedisPoolConfig.maxIdle}" />
    <property name="maxWaitMillis"
        value="${redis.cluster.jedisPoolConfig.maxWaitMillis}" />
    <property name="testOnBorrow"
        value="${redis.cluster.jedisPoolConfig.testOnBorrow}" />
</bean>

<bean id="jedisConnectionFactory"
    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <constructor-arg ref="redisClusterConfiguration" />
    <constructor-arg ref="jedisPoolConfig" />
    <property name="password" value="${redis.cluster.jedisConnectionFactory.password}" />
</bean>

<bean id="stringRedisSerializer"
    class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean id="jdkSerializer"
    class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory">
    <!-- 序列化方法 -->
    <property name="keySerializer" ref="stringRedisSerializer" />
    <property name="hashKeySerializer" ref="stringRedisSerializer" />
    <property name="valueSerializer" ref="jdkSerializer" />
    <property name="hashValueSerializer" ref="jdkSerializer" />
</bean>

<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory" />

<bean id="redisHttpSessionConfiguration"
      class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
    <!--超时时间,默认1800秒-->
    <property name="maxInactiveIntervalInSeconds" value="1800" />
</bean>
注:对应的属性文件是: #Redis Cluster redis.cluster.maxRedirects=3

redis.cluster.host1=192.168.1.30
redis.cluster.port1=7000

redis.cluster.host2=192.168.1.30
redis.cluster.port2=7001

redis.cluster.host3=192.168.1.30
redis.cluster.port3=7002

redis.cluster.host4=192.168.1.224
redis.cluster.port4=7003

redis.cluster.host5=192.168.1.224
redis.cluster.port5=7004

redis.cluster.host6=192.168.1.224
redis.cluster.port6=7005

#JedisPoolConfig
redis.cluster.jedisPoolConfig.maxTotal=1024
redis.cluster.jedisPoolConfig.maxIdle=20
redis.cluster.jedisPoolConfig.maxWaitMillis=100000
redis.cluster.jedisPoolConfig.testOnBorrow=true

扫描二维码关注公众号,回复: 3270459 查看本文章

#JedisConnectionFactory
redis.cluster.jedisConnectionFactory.password=admin
(3)修改web.xml:
在web.xml中添加以下filter:


springSessionRepositoryFilter
org.springframework.web.filter.DelegatingFilterProxy


springSessionRepositoryFilter
/*

注:需要将这个filter放在第一位,其他的如编码、shiro等filter需要放在这之后
到此,Spring Session和Spring Data Redis就整合到项目中了
(4)测试:
运行项目后,可以发现生成了一个名为“SESSION”的cookie。接着在我们登录之后,可以通过其cookie值在redis上取得保存的对应的session对象。如下图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/luzhuhong1/article/details/82770268