Session 共享方案

一.nginx+tomcat+redis方案

nginx+tomcat+redis

1.redis配置(192.168.159.131:16300)

2.tomcat配置

tomcat1(192.168.159.130:8081)

tomcat2(192.168.159.130:8082)

3.nginx安装在192.168.159.131。

      首先,是配置tomcat,使其将session保存到redis上。有两种方法,也是在server.xml或context.xml中配置,redis需要增加的内容如下:

(注意:valve标签一定要在manager前面。)

配置找到Context节点,在context中加入

<ValveclassName="com.radiadesign.catalina.session.RedisSessionHandlerValve"/>
 <ManagerclassName="com.radiadesign.catalina.session.RedisSessionManager"
         host="192.168.159.131"
          port="16300"
          database="0"
         maxInactiveInterval="60"/>

其次,配置nginx,用于测试session保持共享。

upstream redis.xxy.com {
       server   192.168.159.130:8081;
       server   192.168.159.130:8082;
 }log_format www_xy_com '$remote_addr - $remote_user [$time_local] $request '
               '"$status"$body_bytes_sent "$http_referer"' 
               '"$http_user_agent""$http_x_forwarded_for"';server
 {
       listen  80;
       server_name redis.xxy.com; location/ {
               proxy_pass         http://redis.xxy.com;
               proxy_set_header  Host            $host;
               proxy_set_header  X-Real-IP        $remote_addr;
               proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
       }access_log /data/base_files/logs/redis.xxy.log  www_xy_com;
 }

最后,将你的应用放到两个tomcat中,并依次启动redis、tomcat、nginx。访问你的nginx,可以发现两个tomcat中的session可以保持共享了。

 

 

二.基于Spring Session实现Session的分布式管理

 

 

Spring Session作为Spring社区官方推荐的一个比较简单快速的Java Web分布式session解决方案,帮我们搞定了长期以来比较蛋疼的session分布式的问题。

Spring Session解决的基本思路很简单,即将用户的session信息全部存放到一个redis数据库中,所有的session都从这个数据库拿。由于 redis是一个内存数据库,数据信息读写是非常快速的。如此一来,多个Tomcat,共用一个redis数据库,即实现了session的共享问题。

在百度中查询Spring Session即可找到SpringSession的官方站点。

 

Maven工程pom.xml依赖

<!-- Redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.4.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.5.2</version>
</dependency>
<!-- Spring Session -->
<dependency>
       <groupId>org.springframework.session</groupId>
       <artifactId>spring-session</artifactId>
       <version>1.0.2.RELEASE</version>
</dependency>
<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>2.2</version>
</dependency>

我们这里,首先,配置spring-data-redis和jedis,这样,就可以使用spring-data-redis框架,来实现访问redis数据库。

spring-data-redis是spring的一个子项目,和spring-session一样。spring-session要访问redis,这里spring-session依赖spring-data-redis,来实现操作reids数据库。

 

 

 

 

Spring Core、Spring Web需要配置4.x版本。

当然,Spring Session还需要把Spring Web等常见的Spring包引入。Spring Session 1.0.2依赖Spring的版本为4.1.6以上,因此,3.x版本的Spring是无法使用的:

可以从Maven Repository查看依赖情况:http://mvnrepository.com/artifact/org.springframework.session/spring-session/1.0.2.RELEASE

此外,注意javax.servlet-api需要3.0.1版本以上。

配置application-context.xml文件

这里,我们以使用xml配置方式为例,当然也可以使用注解配置,详见SPring的官方例子(见参考资料)

备注:xml的配置方法官方给出了一个例子:http://docs.spring.io/spring-session/docs/1.0.2.RELEASE/reference/html5/guides/httpsession-xml.html

在application-context.xml文件中,加入:

<context:annotation-config/> 
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/> 
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" />    
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"  p:pool-config-ref="poolConfig"/>

其中,${redis.host}等即redis数据库的服务器地址,端口,密码等信息,放在properties文件中即可。

 

修改web.xml,加入Spring Session的Filter

在web.xml文件中,加入:

<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>

这样,所有的请求,都会被DelegatingFilterProxy处理,实际上,DelegatingFilterProxy会找到 springSessionRepositoryFilter,创建它。每一次的请求还是由springSessionRepositoryFilter来过滤的。

The DelegatingFilterProxy will look up a Bean by the name of springSessionRepositoryFilter and cast it to a Filter. For every request that DelegatingFilterProxy is invoked, the springSessionRepositoryFilter will be invoked.

这里,Spring加入了一个Filter,其本质是:对每一个请求的request进行了一次封装。那么,在Controller里面拿出的request实际上是封装后的request,

调用request.getSession()的时候,实际上拿到是Spring封装后的session。这个session则存储在redis数据库中。

session对象被序列化后存入。因此,所有放入session的对象,都要实现Serializable接口。比如,我将所有的用户信息,封装到一个Authentication对象,那么

这对象就必须实现Serializable接口:

如果要设置Session的过期时间,通常我们会在web.xml文件中进行设置:

但是,使用Spring Session托管session后,这里的设置将会失效。我们要专门为Spring Session进行设置:

将 application-context.xml,即步骤4中的的RedisHttpSessionConfiguration,设置其maxInactiveIntervalInSeconds属性即可。注意,maxInactiveIntervalInSeconds的的单位是秒! 如下将设置session为10分钟过期!

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="maxInactiveIntervalInSeconds" value="600"></property>
</bean>




博主推荐第二套 目前项目中所用