170222、使用Spring Session和Redis解决分布式Session跨域共享问题
使用Spring Session和Redis解决分布式Session跨域共享问题
前言
对于分布式使用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提供以下特性:
API和用于管理用户会话的实现;
HttpSession - 允许以应用程序容器(即Tomcat)中性的方式替换HttpSession;
Clustered Sessions - Spring Session让支持集群会话变得不那么繁琐,并且不和应用程序容器金习性绑定到。
Multiple Browser Sessions - Spring会话支持在单个浏览器实例中管理多个用户的会话。
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跨域共享问题的更多相关文章
- 使用Spring Session和Redis解决分布式Session跨域共享问题
http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题
- 使用SpringSession和Redis解决分布式Session共享问题
SpringSession优势 遵循servlet规范,同样方式获取session,对应用代码无侵入且对于developers透明化 关键点在于做到透明和兼容 接口适配:仍然使用HttpServlet ...
- 通过jsonp解决浏览器的跨域共享
因为浏览器的同源策略,普通ajax访问跨域请求返回的json数据是不会被浏览器接受的.看下面例子可以看出是访问不到的 首先 定义webapi 后台代码 public class JsopControl ...
- Spring Session解决分布式Session问题的实现原理
使用Spring Session和Redis解决分布式Session跨域共享问题 上一篇介绍了如何使用spring Session和Redis解决分布式Session跨域共享问题,介绍了一个简单的案例 ...
- Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架
Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloop import tornado.web from myhas ...
- 跨域共享cookie和跨域共享session
转载自:http://blog.csdn.net/ahhsxy/article/details/7356128 这里所说的跨域,是指跨二级域名,而且这些域名对应的应用都在同一个app上, 比如我有以下 ...
- session跨域共享问题解决方案
在讨论 session 跨域共享问题之前,我们首先要了解 session 做了什么,没做什么 1.HTTP是无状态的,也就是说服务器不知道谁访问过他,但是有时间,又需要我们去保留这个状态比如说用户的登 ...
- session跨域共享解决方案
要让session跨域共享,需要解决三个问题: 1.通过什么方法来传递session_id? 2.通过什么方法来保存session信息? 3.通过什么方法来进行跨域? 一.传递session_id有4 ...
- C#彻底解决Web Browser 跨域读取Iframes内容
C#彻底解决Web Browser 跨域读取Iframes内容 用C# winform的控件web browser 读取网页内容,分析一下数据,做一些采集工作. 如果是同一个域名下面还是好办的,基本上 ...
随机推荐
- excel导入sql server 文本被截断,或者一个或多个字符在目标代码页中没有匹配项 错误处理
excel导入sql server 文本被截断,或者一个或多个字符在目标代码页中没有匹配项 错误处理方法: 方案1:修改注册表 出现文本被截断的原因是SQL Server的导入导出为了确定数据表的字段 ...
- CGGeometry Reference
CGRectUnionCGRectUnion接受两个CGRect结构体作为参数并且返回一个能够包含这两个矩形的最小矩形.听起来可能没什么,我相信你也可以用几行代码轻松实现这个功能,不过 CGGeome ...
- A Translation for Quaternion 一篇对四元数的翻译
一篇写的非常好的博客:http://www.cnblogs.com/lookof/archive/2012/02/24/2360749.html
- Ubuntu11.04中如何将pycharm添加到系统的“应用程序”菜单里 (pycharm已成功安装)
默认排序 Stu.zhouyc 21 人赞同了该回答 tools---->create desktop entry...不是很方便吗? 发布于 2016-04-09 21添加评论 分享 收藏 ...
- [docker]docker日志驱动记录nginx日志情形探究
这里研究下容器nginx记录日志的集中情况,主要想弄明白,docker的日志--log-driver=fluentd 改成fluentd后,会不会在本地在记录一份日志 整体架构是这样的 情况1: 首先 ...
- 如何将git 关联到Pycharm
一,预置条件 1,安装pycharm 2,安装git 仓库 二,关联步骤 1,打开Pycharm File | Settings | Version Control | Git 2,配置需要关联的 ...
- 架设HmailServer邮件服务器以及webmail
参考:http://www.it0355.com/a/201207/31/a9275.htm 在安裝Hmailserver前先安裝Apache.php.mysql,如果你想懶點直接到http://ww ...
- VirtualBox虚拟机和主机之间的通信
- VirtualBox的NAT网络模式,主机不能访问虚拟机- 端口转发可以访问,但是性能非常差,第一次连接30秒左右- 有条件的还是推荐VmWare
- Zabbix exp编写
#/usr/bin/python #*-*coding=utf-8*-* import urllib logo = '''\n _____ _ _ _ _____ _ |__ /__ _| |__ | ...
- (译)Getting Started——1.2.1 Defining the Concept(确定理念)
每个出色的应用都是由理念开始的.在开发应用时,你不需要把理念完善和完成后再进行开发.但是你确实需要确定你要做什么,做完后的效果如何. 为了定义理念,问自己以下的问题: 应用的受众是哪些人?应用的内容和 ...