SpringSession基于Redis存储的序列化问题

阅读: 评论:0

SpringSession基于Redis存储的序列化问题
在微服务开发过程中,为了使⽤⽅便经常会将频繁访问的信息如⽤户、权限等放置到SESSION中,便于服务访问,⽽且,微服务间为了共享SESSION,通常会使⽤Redis共享存储。但是这样就会有⼀个问题,Spring boot在封装Request对象时会将当前SESSION中所有属性对象反序列化,反序列化都成功以后,将SESSION对象⽣成。如果有⼀个微服务将本地的⾃定义Bean对象放置到SESSION中,则其他微服务都将出现反序列化失败,请求异常,服务将不能够使⽤了,这是⼀个灾难性问题。
如何解决这个问题呢?
需要了解⼀下Spring redis SESSION 是如何进⾏反序列化的。
Spring session针对Web的Request请求有⼀个org.springframework.session.web.http.SessionRepositoryFilter过滤器,根据SESSION ID获取相应的SESSION对象。
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFilter{
...
private final SessionRepository<S> sessionRepository;
...
}
SessionRepositoryFilter会调⽤sessionRepository.findById(sessionId)来查SESSION对象,对于Redis,sessionRepository 的实现类为org.springframework.dis.RedisOperationsSessionRepository,通过查看源码,可以看到,该类默认的序列化类为org.dis.serializer.JdkSerializationRedisSerializer.
通脉汤public class RedisOperationsSessionRepository implements
矫姿带FindByIndexNameSessionRepository<RedisOperationsSessionRepository.RedisSession>,
MessageListener {
...
private RedisSerializer<Object> defaultSerializer = new JdkSerializationRedisSerializer();
.
..
}
通过查询JdkSerializationRedisSerializer源码,发现该类在反序列化时如果异常会抛出SerializationException异常,⽽SessionRepositoryFilter⼜没有处理异常,故如果序列化异常时就会导致请求异常。
public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {
private final Converter<Object, byte[]> serializer;
private final Converter<byte[], Object> deserializer;
/**
* Creates a new {@link JdkSerializationRedisSerializer} using the default class loader.
*/
public JdkSerializationRedisSerializer() {
this(new SerializingConverter(), new DeserializingConverter());
}
/**
* Creates a new {@link JdkSerializationRedisSerializer} using a {@link ClassLoader}.
*
* @param classLoader
* @since 1.7
*/
public JdkSerializationRedisSerializer(ClassLoader classLoader) {
this(new SerializingConverter(), new DeserializingConverter(classLoader));
}
/
**
* Creates a new {@link JdkSerializationRedisSerializer} using a {@link Converter converters} to serialize and
* deserialize objects.
*
* @param serializer must not be {@literal null}
* @param deserializer must not be {@literal null}
* @since 1.7
*/
public JdkSerializationRedisSerializer(Converter<Object, byte[]> serializer, Converter<byte[], Object> deserializer) {
this.serializer = serializer;
this.deserializer = deserializer;
}
电路板测试台
public Object deserialize(@Nullable byte[] bytes) {
智能脱扣器if (SerializationUtils.isEmpty(bytes)) {
return null;
非接触测量
}
try {
vert(bytes);
} catch (Exception ex) {
throw new SerializationException("Cannot deserialize", ex);
}
}
@Override
public byte[] serialize(@Nullable Object object) {
if (object == null) {
return SerializationUtils.EMPTY_ARRAY;
}
try {
vert(object);
} catch (Exception ex) {
throw new SerializationException("Cannot serialize", ex);
}
}
}
这样我们就明⽩了异常的来源,那就想办法解决这个异常了,如何解决这个异常呢?定制Spring redis session的序列化类,替代原有的默认的JdkSerializationRedisSerializer。
⽹上也有好多关于Redis序列化定制的介绍,⼤部分经过验证对于Spring redis Session不起作⽤,⽽且有些定制太多,直接将sessionRepository进⾏了定制,这样是可以,但是感觉有点⼤材⼩⽤了,那应该如何定制SESSION满⾜系统场景需要呢?
电厂脱硫滤布通过查发现,Github spring-session ISSUE中有类似定制反序列的答案,链接如下:
通过⾃定义springSessionDefaultRedisSerializer对象,将会替代默认的SESSION序列化对象。如何实现这个⾃定义的序列化对象呢?
这样需要回到上⾯我们提到的Session,Redis共享⾯临可能出现毁灭性事故的情形,某个微服务将⾃定义Bean对象保存到Session中导致其他微服务请求异常。所以,在实现定制的序列化对象时,对于反序列化失败时,⼀定不能抛出异常,避免系统请求中断。
如何做到⾃定义的序列化对象不抛异常呢?
1.    在原有序列化JdkSerializationRedisSerializer对象的基础上,在反序列化异常时捕获这个异常,仅记录相关⽇志即可。
@Component("springSessionDefaultRedisSerializer")
public class CustomSessionDefaultRedisSerializer extends JdkSerializationRedisSerializer {
private static final Logger LOG = Logger(CustomSessionDefaultRedisSerializer.class);
public Object deserialize(@Nullable byte[] bytes) {
Object deserialObj = null;
try
{
deserialObj =  super.deserialize(bytes);
}
catch(Exception e)
{
LOG.warn("deserialize session Object error!", e);
}
return deserialObj;
}
}
2. ⾃定义的序列化对象在序列化与序列化中,将保存到Session中的对象都转换成JSON字符串保存,这样就要求所有保存到Session中
的对象都为普通的Bean对象。这种定制序列化对象⽅式,没有试验,理论上应该可⾏。
这是当前⾃⼰能⼒所限制,能够想到解决这个问题的⽅法,也许还有更好,更完美的⽅式,也可以⼤家⼀起讨论。

本文发布于:2023-06-28 09:06:01,感谢您对本站的认可!

本文链接:https://patent.en369.cn/patent/2/155529.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:序列化   对象   服务   定制   定义
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图