您的位置:首页 > 数据库 > Redis

spring Session + Redis集群 + 哨兵部署下实现Session共享

2017-12-22 13:28 776 查看
1.共享Session问题

HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。而如果我们把web服务器搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到两个不同的web站点中去。那么问题就来了,如何保证不同的web站点能够共享同一份session数据呢?

最简单的想法就是把session数据保存到内存以外的一个统一的地方,例如Memcached/Redis等数据库中。那么问题又来了,如何替换掉Servlet容器创建和管理HttpSession的实现呢?

(1)设计一个Filter,利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。spring-session就是通过这样的思路实现的。
(2)利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。不过这种方式有个缺点,就是需要耦合Tomcat/Jetty等Servlet容器的代码。这方面其实早就有开源项目了,例如memcached-session-manager,以及tomcat-redis-session-manager。暂时都只支持Tomcat6/Tomcat7。

2.Spring Session介绍


Spring Session是Spring的项目之一,GitHub地址:https://github.com/spring-projects/spring-session。

Spring Session提供了一套创建和管理Servlet HttpSession的方案。Spring Session提供了集群Session(Clustered Sessions)功能,默认采用外置的Redis来存储Session数据,以此来解决Session共享的问题。

下面来一个demo展示一下我的实现方式
3.Maven依赖

<!-- Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!-- Spring Data Redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.3.RELEASE</version>
</dependency>
<!-- Spring Session -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
<!-- Apache Commons Pool -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>

4、配置filter

web.xml:

<!-- 分布式Session共享Filter -->
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

5、redis.properties

 由于redis是多节点集群哨兵配置,故此有三个连接ip

# Redis settings
redis.sentinels1=192.168.0.157
redis.sentinels2=192.168.0.160
redis.sentinels3=192.168.0.164
redis.sentinel.port=26379
#sentinel\u7684\u9274\u6743\u5bc6\u7801
redis.sentinel.masterName=mymaster
redis.sentinel.password=raymond
#\u6700\u5927\u95f2\u7f6e\u8fde\u63a5\u6570
redis.maxIdle=500
#\u6700\u5927\u8fde\u63a5\u6570\uff0c\u8d85\u8fc7\u6b64\u8fde\u63a5\u65f6\u64cd\u4f5credis\u4f1a\u62a5\u9519
redis.maxTotal=5000
redis.maxWaitTime=1000
redis.testOnBorrow=true
redis.testOnReturn=false
redis.testWhileIdle=false
#\u6700\u5c0f\u95f2\u7f6e\u8fde\u63a5\u6570\uff0cspring\u542f\u52a8\u7684\u65f6\u5019\u81ea\u52a8\u5efa\u7acb\u8be5\u6570\u76ee\u7684\u8fde\u63a5\u4f9b\u5e94\u7528\u7a0b\u5e8f\u4f7f\u7528\uff0c\u4e0d\u591f\u7684\u65f6\u5019\u4f1a\u7533\u8bf7\u3002
redis.minIdle=300

6、spring文件配置

applicationContext.xml 里面引入spring-redis.xml文件

<import resource="classpath:spring-redis.xml" />


spring-redis.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd ">

<!-- spring session -->
<bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="1800"/>
</bean>

<!-- reids连接工厂配置 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<constructor-arg name="sentinelConfig" ref="sentinelConfiguration"/>
<constructor-arg name="poolConfig" ref="poolConfig"/>
<property name="password" value="${redis.sentinel.password}"/>
</bean>

<!-- redis连接池配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxWaitMillis" value="${redis.maxWaitTime}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
<property name="testOnReturn" value="${redis.testOnReturn}" />
<property name="testWhileIdle" value="${redis.testWhileIdle}" />
</bean>

<!-- redis分布式 哨兵配置 -->
<bean id="sentinelConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
<property name="master">
<bean class="org.springframework.data.redis.connection.RedisNode">
<property name="name" value="${redis.sentinel.masterName}"></property>
</bean>
</property>
<property name="sentinels">
<set>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.sentinels1}"></constructor-arg>
<constructor-arg name="port" value="${redis.sentinel.port}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.sentinels2}"></constructor-arg>
<constructor-arg name="port" value="${redis.sentinel.port}"></constructor-arg>
</bean>
<bean class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg name="host" value="${redis.sentinels3}"></constructor-arg>
<constructor-arg name="port" value="${redis.sentinel.port}"></constructor-arg>
</bean>
</set>
</property>
</bean>
</beans>

注意:使用spring session有版本限制,这个版本问题坑坏我了,经过多次试验,才把本公司项目session共享搞定,由于本公司项目没有采用maven管理,故我把自己的jar包也发出来了,以供大家自行下载使用,地址:点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: