Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 474|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-28 09:45:32 | 显示全部楼层 |阅读模式

    使用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提供以下特性:

    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就能解决,这边博文只是提供一个思路!

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-4 14:03 , Processed in 0.059297 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表