关于SpringSession相关的介绍和使用指南,可移步如下网址:

【SpringSession管理分布式系统的会话Session】

https://www.cnblogs.com/captainad/p/10861006.html

问题浮现

我们在使用SpringSession时(其实在问题出现时,我们并没有意识到和这儿有关联),遇到了一个隐藏较深的问题。我们像往常一样,在用户登录成功之后,将用户的实体类信息实例化保存到了session中,且session最后保存到了redis里面,这个过程其实是没有什么问题的。

随着时间的推移业务的迭代变化,用户实体需要为更新的需求增加额外的字段,于是我们顺其自然的在类中追加其他String类型的属性,结果上了测试环境,发现我们无法进入到登录页面,从浏览器控制台上我们发现这个请求因为无法获取正确的鉴权而不断报302,并且浏览器错误主页提示我们“清除浏览器cookie”,当我们照做之后,登录页面神奇般的可以打开并且我们能够顺利登录系统和使用系统了。在我们回到服务端查看后台日志时,我们看到时在redis中出现了反序列化的问题,而且日志报的很蹊跷,并不是我们的业务代码的某一行直接抛出的日志,这给我们定位问题带了一点麻烦。

分析问题

首先反序列化出现问题,我们首先能够想到的就是给用户实体加了额外属性导致的,但是为何会出现反序列化问题呢?原因看起来很简单,我们的用户实体类确实实现了Serializable接口,但是我们并没有显示的写出序列化的serialVersionUID,这在实体变更了属性字段之后反序列化回来,就一定会反序列化失败的,因为在你没有指定序列号serialVersionUID号的时候,系统默认都是以类名称类属性等来自动生成的,不同的属性名称得出的序列化值肯定是不一样的,解决的方法很简单,就是在初始化类的时候,主动写名序列化serialVersionUID号。

但是我们的程序现在已经在生产环境了,无法做到这一步,因为按照新的类来生成序列号,显然是前后不一致的,给新加的字段加上transient字段?这种做法也步行,这意味着这个字段的值将无法序列化,后面其他系统肯定是使用不了的,这些额外增加的字段就没有存在意义了。

在对报错日志进行抽丝剥茧逐行分析之后,发现这个异常居然和SpringSession有关系。

因为我们在用户成功登录系统之后,使用了request.getSession().setAttribute("xx", "xx")操作,我们将我们的用户实体放到了session中,并由SpringSession成功的放到了Redis里面,并且我们的会话时长是48小时;在我们新的实体更新进来之后,系统一发布,打开登录页面系统对SpringSession中的内容进行初始化,就发现了用户实体无法从Redis中初始化回来,因为前后的序列化号对不上了,于是就疯狂的报反序列化失败,这是根本问题所在。

解决问题

那怎么解决呢?很明显,聪明的浏览器给了我们第一个解决方案,那就是清除浏览器Session。

因为上面我们说到,SpringSession会在浏览器里面自动设置一个名为SESSION的cookie值,这个值是为了后台服务能够在Redis中找到之前存放的Session以便能够识别是统一用户,当浏览器清除了Cookie之后,这个SESSION的值就失去了,于是系统重新为这个浏览器发起请求的用户重新生成SESSION值,这个请求也就无法在redis中找到对应的Session会话,也就没有将用户实体反序列化这个过程,登录程序当然能够正常进行,而且往后的交互都是正常的了。

那么还有另外的解决方法,从Redis端,既然SpringSession会用这个SESSION去Redis中找对应的值,那么我们就将这个Redis中存放的Session内容进行清除,找不到内容自然就无需反序列化了,不过此时正常访问的用户,也会因为请求没有找到统一的Session而认为是会话过期强制退出。这里在redis中清除内容的方式,可以使用下面的命令:

$ redis-cli keys '*' | xargs redis-cli del
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

第三种方式呢,就是从代码端改造,反序列化失败的本质就是原来的类新增了属性,而且类没有显示的指定序列化serialVersionUID,那么我们变通一下,保持原来的类不变呗,新增的属性放到一个继承了这个用户实体类的类当中,后面我们就用这个新的类,保持老的类不变(属性类型和数量等的都不变),那就行了。是的,就是使用新类的方式,新类继承用户实体类,保持用户实体类不变,新类当中增加需要补充的属性字段,同时需要序列化,这样SpringSession在初始化时,它依然能够反序列找到原来没有变通的那个类,我们自己也能够很好的实现我们新的需求了。

问题总结

通过上面的分析我们可以发现,其实SpringSession是替换了HttpSession并在序列化之后存入了Redis里面的,隐藏较深的持久化对外部没有写明serialVersionUID的对象进行的变化较为敏感,如果一旦遗漏了这个细节,在日后变更属性之后,可能就会暴露出这个问题,而且因为牵扯到用户登录鉴权,这种影响算是较为恶劣,所以平时应该留意这种小错误,尽可能在对象实现序列化之后写名serialVersionUID,相信这是一种好习惯,当然,可以设置IDEA让它自动检测,如果你实现了Serializable接口但是没有生成serialVersionUID就报错提醒。希望这次的问题分析能够对日后使用SpringSession有所帮助,能够想周到一点,想深入一点。

使用SpringSession管理分布式会话时遇到的反序列化问题的更多相关文章

  1. 使用SpringSession管理分布式系统的会话Session

    在我方供应链项目分布式部署的环境下,需要在统一网关服务中管理访问的Session,即无论访问请求路由到哪一个网关服务环境,使用的都是相同的HttpSession,这样就保证了在用户登录之后,能够使用统 ...

  2. 第二十三章 多项目集中权限管理及分布式会话——《跟我学Shiro》

    二十三章 多项目集中权限管理及分布式会话——<跟我学Shiro> 博客分类: 跟我学Shiro 跟我学Shiro  目录贴:跟我学Shiro目录贴 在做一些企业内部项目时或一些互联网后台时 ...

  3. 补习系列(15)-springboot 分布式会话原理

    目录 一.背景 二.SpringBoot 分布式会话 三.样例程序 四.原理进阶 A. 序列化 B. 会话代理 C. 数据老化 小结 一.背景 在 补习系列(3)-springboot 几种scope ...

  4. 利用 ssh 的用户配置文件 config 管理 ssh 会话

    http://dhq.me/use-ssh-config-manage-ssh-session 利用 ssh 连接远程服务器,一般都要输入以下类似命令: 1 ssh user@hostname -p ...

  5. 004-restful应用构建、分布式会话、测试工具简介

    一.概述 什么是rest(表述性状态转移,Representational State Transfer)是一种架构风格.他定义了创建可扩展Web服务的最佳实践. 1.Richardson成熟度模型 ...

  6. 利用ssh的用户配置文件config管理ssh会话

    通常利用 ssh 连接远程服务器,一般都要输入以下类似命令: ssh user@hostname -p port 如果拥有多个 ssh 账号,特别是像我这种喜欢在终端里直接 ssh 登陆,不用 PuT ...

  7. 阶段5 3.微服务项目【学成在线】_day08 课程图片管理 分布式文件系统_06-分布式文件系统研究-fastDFS安装及配置文件说明

    3 fastDFS入门 3.1fastDFS安装与配置 3.1.1 导入虚拟机 对fastDFS的安装过程不要求学生掌握,可以直接导入老师提供虚拟机. 1.使用Vmware打开虚拟机配置文件“Cent ...

  8. 使用Redis实现分布式会话

    1. 概述 传统的单体应用中,用户是否登录,通常是通过从Tomcat容器的session中获取登录用户信息判断的. 但在分布式的应用中,通常负载均衡了多台Tomcat,每台Tomcat都有自己独立的s ...

  9. Dapr中国社区活动之 分布式运行时开发者日 (2022.09.03)

    自2019年10月首次发布以来,Dapr(Distributed Application Runtime,分布式应用运行时)因其"更稳定"."更可靠".&quo ...

随机推荐

  1. xdu2017校赛F

    Problem F Dogs of Qwordance Senior Backend R&D Engineers 问题描述 那年夏天,锘爷和杰师傅漫步在知春公园的小道上.他们的妻子.孩子牵 着 ...

  2. 6、R语言绘制带errorbar 的柱状图

    转载:http://www.cnblogs.com/xudongliang/p/7283733.html data <- data.frame(mean = c(10, 15), sd = c( ...

  3. p1640&bzoj1854 连续攻击游戏(游戏)

    传送门(洛谷) 传送门(bzoj) 题目 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用 ...

  4. 聪明的kk (南洋理工—171)

    #include<iostream> using namespace std; ][]; ][]; int N, M; int dp(int i, int j) { ) return d[ ...

  5. 如何修改html中列表项li所显示的圆点的颜色?,以及相关样式的设定

    这是li标签自带的圆点的颜色改变,代码如下: .centerbt li{ content:"."; color:gray; } 在标签li后面加入“@”符号,这里都会使用posit ...

  6. Dropout和学习率衰减

         Dropout 在机器学习的模型中,如果模型的参数太多,而训练样本又太少,训练出来的模型很容易产生过拟合的现象.在训练神经网络的时候经常会遇到过拟合的问题,过拟合具体表现在:模型在训练数据上 ...

  7. 51nod 1354【DP】

    (我一定是A了一题假DP) 给定序列a[0],a[1],a[2],...,a[n-1] 和一个整数K时, 有多少子序列所有元素乘起来恰好等于K. K<=1e8; 思路: 感觉 k 的 约数是突破 ...

  8. Unity 着色器训练营(2) - MVP转换和法线贴图

    https://mp.weixin.qq.com/s/Qf4qT15s9bWjbVGh7H32lw 我们刚刚公布了Unity 2018.1中,Unity将会内置可视化编程工具Shader Graph, ...

  9. java IO流部分知识点

    IO流部分 IO流常用的有:字符流.字节流.缓冲流.序列化流.RandomAccessFile类等 1.字节流 FileInputStream/FileOutputStream BufferedInp ...

  10. java解析xml实例——获取天气信息

    获取xml并解析其中的数据: package getweather.xml; import java.io.IOException; import java.util.HashMap; import ...