使用Spring Session和Redis解决分布式Session跨域共享问题

原创 2017-02-27 徐刘根 Java后端技术

前言

对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash、轮训、根据权重、随机等。不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现session不同步或者丢失的问题。

实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat、Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中。

在以前写的一篇文章中:

使用Redis存储Nginx+Tomcat负载均衡集群的Session

这一篇文章中已经学习了一下,如何使用 tomcat-redis-session-manager 开源项目解决分布式session跨域的问题,他的主要思想是利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。tomcat-redis-session-manager重写了Tomcat的org.apache.catalina.session.ManagerBase里边的具体写的操作, 将tomcat的session存储位置指向了Redis:

RedisSessionManager继承了org.apache.catalina.session.ManagerBase并重写了add、findSession、createEmptySession、remove等方法,并将对session的增删改查操作指向了对Redis数据存储的操作。

有兴趣可参考一篇Tomcat中session的管理机制:http://www.cnblogs.com/interdrp/p/4935614.html

不过使用过tomcat-redis-session-manager 的都应该知道,配置相对还是有一点繁琐的,需要人为的去修改Tomcat的配置,需要耦合Tomcat等Servlet容器的代码,并且对于分布式Redis集群的管理并不是很好,与之相对的个人认为比较好的一个框架spring Session可以真正对用户透明的去管理分布式Session。

Spring Session不依赖于Servlet容器,而是Web应用代码层面的实现,直接在已有项目基础上加入spring Session框架来实现Session统一存储在Redis中。如果你的Web应用是基于Spring框架开发的,只需要对现有项目进行少量配置,即可将一个单机版的Web应用改为一个分布式应用,由于不基于Servlet容器,所以可以随意将项目移植到其他容器。

Spring Session使用

官方地址:http://projects.spring.io/spring-session/

官方文档地址:http://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/

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

一、特性

Spring Session提供以下特性:

  1. API和用于管理用户会话的实现;

  2. HttpSession - 允许以应用程序容器(即Tomcat)中性的方式替换HttpSession;

    1. Clustered Sessions - Spring Session让支持集群会话变得不那么繁琐,并且不和应用程序容器金习性绑定到。

    2. Multiple Browser Sessions - Spring会话支持在单个浏览器实例中管理多个用户的会话。

    3. RESTful APIs - Spring Session允许在headers 中提供会话ID以使用RESTful API。

 

二、基于XML配置方式的Spring Session案例实现

基于SSM框架的一个小案例,Git OS项目代码地址:http://git.oschina.net/xuliugen/spring-session-demo

项目展示:

(1)基本环境需求

进行使用Spring Session的话,首先的是已经安装好的有一个 Redis服务器!

(2)添加项目依赖(最基本的依赖使用)

(3)添加Spring配置文件

添加了必要的依赖之后,我们需要创建相应的Spring配置。Spring配置是要创建一个Servlet过滤器,它用Spring Session支持的HttpSession实现来替换容器本身HttpSession实现。这一步也是Spring Session的核心。

上述代码注释:

LettuceConnectionFactory实例是配置Redis的ConnectionFactory。

注意:

查看源代码可以看到,默认的Redis链接配置为:

因此,如果有自己的Redis配置,请修改,例如下边的配置:

(5)关于Error creating bean with name ‘enableRedisKeyspaceNotificationsInitializer’错误的处理:

添加如下配置让Spring Session不再执行config命令:

如果不添加的话,会报如下错误:

Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name'enableRedisKeyspaceNotificationsInitializer' defined in classpath resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]: Invocation of initmethod failed; nested exception isjava.lang.IllegalStateException: Unable to configure Redis tokeyspace notifications. See http://docs.spring.io/spring-session/docs/current/reference/html5/#api-redisoperationssessionrepository-sessiondestroyedeventCausedby: redis.clients.jedis.exceptions.JedisDataException: ERR unknown command config

(5)在web.xml中添加DelegatingFilterProxy

DelegatingFilterProxy将通过springSessionRepositoryFilter的名称查找Bean并将其转换为过滤器。对于调用DelegatingFilterProxy的每个请求,也将调用springSessionRepositoryFilter。

(6)Spring MVC controller代码用于测试

(7)测试

访问链接:http://localhost:8080/spring/session/setSession.do?name=xuiliugen&value=123456

使用工具查看Redis内容:

可以发现已经有值了!并且有expirations,可以看到箭头指向的位置,是失效的时间记录值!

(8)到此,Spring Session的使用已经完成!其他具体的细节请参考:http://git.oschina.net/xuliugen/spring-session-demo 项目源代码。

总结

对于分布式环境Session跨域共享的问题,不管是使用开源的框架还是使用自己开发的框架,都需要明白的一个问题是:在Tomcat容器中创建Session是一个很耗费内存的事情。因此,我们在自己写类似框架的时候,我们一定要注意的是,并不是Tomcat为我们创建好了Session之后,我们首先获取Session然后再上传到Redis等进行存储,而是直接有我们自己创建Session,这一点是至关重要的!

注:其实可以使用token+redis就能解决,这边博文只是提供一个思路!

170222、使用Spring Session和Redis解决分布式Session跨域共享问题的更多相关文章

  1. 使用Spring Session和Redis解决分布式Session跨域共享问题

    http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题

  2. 使用SpringSession和Redis解决分布式Session共享问题

    SpringSession优势 遵循servlet规范,同样方式获取session,对应用代码无侵入且对于developers透明化 关键点在于做到透明和兼容 接口适配:仍然使用HttpServlet ...

  3. 通过jsonp解决浏览器的跨域共享

    因为浏览器的同源策略,普通ajax访问跨域请求返回的json数据是不会被浏览器接受的.看下面例子可以看出是访问不到的 首先 定义webapi 后台代码 public class JsopControl ...

  4. Spring Session解决分布式Session问题的实现原理

    使用Spring Session和Redis解决分布式Session跨域共享问题 上一篇介绍了如何使用spring Session和Redis解决分布式Session跨域共享问题,介绍了一个简单的案例 ...

  5. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloop import tornado.web from myhas ...

  6. 跨域共享cookie和跨域共享session

    转载自:http://blog.csdn.net/ahhsxy/article/details/7356128 这里所说的跨域,是指跨二级域名,而且这些域名对应的应用都在同一个app上, 比如我有以下 ...

  7. session跨域共享问题解决方案

    在讨论 session 跨域共享问题之前,我们首先要了解 session 做了什么,没做什么 1.HTTP是无状态的,也就是说服务器不知道谁访问过他,但是有时间,又需要我们去保留这个状态比如说用户的登 ...

  8. session跨域共享解决方案

    要让session跨域共享,需要解决三个问题: 1.通过什么方法来传递session_id? 2.通过什么方法来保存session信息? 3.通过什么方法来进行跨域? 一.传递session_id有4 ...

  9. C#彻底解决Web Browser 跨域读取Iframes内容

    C#彻底解决Web Browser 跨域读取Iframes内容 用C# winform的控件web browser 读取网页内容,分析一下数据,做一些采集工作. 如果是同一个域名下面还是好办的,基本上 ...

随机推荐

  1. leetcode——Lowest Common Ancestor of a Binary Tree

    题目 Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. 思路 这一次 ...

  2. 算法----堆排序(heap sort)

    堆排序是利用堆进行排序的高效算法,其能实现O(NlogN)的排序时间复杂度,详细算法分析能够点击堆排序算法时间复杂度分析. 算法实现: 调整堆: void sort::sink(int* a, con ...

  3. CCNA2.0笔记_WAN技术-专线

    WAN拓扑 Routers.CSU/DSU.WAN switches.Core routers.Modems 使用 数据链路层协议(二层) 来建立对端连接 WAN的三种连接方式 广域网链路类型: ·V ...

  4. mysql 求季度产量平均值

    表名:product 表结构: 表数据: 如果使用日期查询的话:sql: SELECT QUARTER(create_time) AS '季度',AVG(seller) AS '平均值' FROM p ...

  5. Oracle基础(三)数据库管理

    上篇介绍了Oracle数据库的基本操作指令:增.删.改.查以下针对数据库的管理进行介绍 数据库角色介绍 数据管理员:  至少有一个数据库管理员dba. 职责:安装和升级oracel数据库 建库,表空间 ...

  6. How to add total page to Odoo Report(7.0 version)

    add this codes to your rml file: <drawRightString x="19.5cm" y="0.3cm">Pag ...

  7. java:eclipse-tomcat 配置

    计划开始学习java.第一步 1.在servers窗口中新建server 2.弹出的界面选择对应的tomcat版本 3.这里是关键,已存在的项目不要选择过去,否则最后生成的server配置无法修改se ...

  8. hdu6000 Wash 巧妙地贪心

    /** 题目:hdu6000 Wash 巧妙地贪心 链接:https://vjudge.net/contest/173364#problem/B 转自:http://blog.csdn.net/ove ...

  9. jQuery设置和获取HTML、文本和值

    jQuery设置和获取HTML.文本和值 按 Ctrl+C 复制代码 <script type="text/javascript"> //<![CDATA[ $( ...

  10. oracle+SQL优化实例

    1.     减少I/O操作: SELECT COUNT(CASE WHEN empno>20 THEN 1 END) c1,COUNT(CASE WHEN empno<20 THEN 1 ...