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

来源:互联网 发布:linux 执行二进制文件 编辑:程序博客网 时间:2024/06/09 14:01

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 settingsredis.sentinels1=192.168.0.157redis.sentinels2=192.168.0.160redis.sentinels3=192.168.0.164redis.sentinel.port=26379#sentinel\u7684\u9274\u6743\u5bc6\u7801redis.sentinel.masterName=mymasterredis.sentinel.password=raymond#\u6700\u5927\u95f2\u7f6e\u8fde\u63a5\u6570redis.maxIdle=500#\u6700\u5927\u8fde\u63a5\u6570\uff0c\u8d85\u8fc7\u6b64\u8fde\u63a5\u65f6\u64cd\u4f5credis\u4f1a\u62a5\u9519redis.maxTotal=5000redis.maxWaitTime=1000redis.testOnBorrow=trueredis.testOnReturn=falseredis.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\u3002redis.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包也发出来了,以供大家自行下载使用,地址:点击打开链接



原创粉丝点击