第三方库shiro-redis所引起的内存泄露问题分析

本文分析了一起由Shiro-Redis库引发的内存泄露问题,表现为系统响应速度下降,CPU占用率高。通过排查,发现是由于ThreadLocalMap中的session未被释放导致。源码分析指出在特定版本的Shiro-Redis中,session过期检查不完整,造成内存堆积。提出了两种解决方案:一是禁用ThreadLocal缓存,二是增强getSessionFromThreadLocal()方法以定期清理超时session。建议升级Shiro-Redis到3.2.3并关闭缓存功能。
摘要由CSDN通过智能技术生成

现象

线上某系统运行不到一周,响应速度变慢,并且多次重启,排查时发现CPU占用到100%,但这段时间系统并发量并未改变,数据库、缓存等也没发现异常。

排查过程

1、top指令查看哪个进程占用CPU高

发现确实是该系统的java进程。

2、使用 top -Hp 进程id 看哪个线程,然后利用jstack命令查看对应线程一直在干什么

很经典的排查线上CPU 100%问题的操作步骤,注意要转十六进制 .

最终发现是GC操作占用CPU。

3、此处怀疑是某处有内存泄露,使用jmap -histo:live 进程id | head -20 查看占用内存最多的对象有哪些

此处注意: ‘jmap’ 命令导出堆转储文件时(‘jmap -dump:live,format=b,file=文件名称 进程id’) 时,会触发Full GC!!!触发Full GC可能导致线上服务不可用。因此要慎重使用,比如如果是多实例部署的话,先隔离一个实例,避免对线上产生影响。‘jmap -histo:live’ 这条命令则没那么恐怖的后果。

由于打印出的结果主要是对象签名,不太容易看,于是最终还是导出了一份堆转储文件,用MAT分析,下面是截图

在这里插入图片描述

参见标红的位置,首先可以看到是某处ThreadLocalMap一直有堆积、没有被释放。

然后进一步往下追,可以看到出问题的地方是org.crazycake.shiro.SessionInMemory,对应的业务对象是UserInfo这个自定义类的对象。

源码分析

org.crazycake.shiro.SessionInMemory 这个类来自于shiro-redis包,用于在shiro中使用redis缓存session。出问题的代码,是shiro-redis 3.2.0版本中的RedisSessionDAO 读取session的代码,如下:

@Override
protected Session doReadSession(Serializable sessionId) {
   
    if (sessionId == null) {
   
        logger.warn("session id is null");
        return null;
    }
    Session s = getSessionFromThreadLocal(sessionId);

    if (s != null) {
   
        return s;
    }

    logger.debug("read session from redis");
    try {
   
        s = (Session) valueSerializer.deserialize(redisManager.get(keySerializer.serialize(getRedisSessionKey(sessionId))))
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
shiro-redis-spring-boot-starter是一个用于集成Apache Shiro和Redis的Spring Boot Starter项目。Apache Shiro是一个强大而灵活的Java安全框架,用于身份验证、授权和会话管理等安全功能。而Redis是一个高性能的内存数据库,其具有快速的数据存取能力和持久化支持。 shiro-redis-spring-boot-starter提供了一种简化和快速集成Shiro和Redis的方式,使得在Spring Boot应用中实现安全功能变得更加容易。通过使用该Starter,我们可以方便地将Shiro的会话管理功能存储到Redis中,从而支持分布式环境下的会话共享和管理。 使用shiro-redis-spring-boot-starter可以带来以下好处: 1. 分布式环境的会话共享:通过将Shiro的会话数据存储到Redis中,不同的应用节点可以共享同一个会话,从而实现分布式环境下的会话管理和跨节点的身份验证和授权。 2. 高可用性和性能:Redis作为一个高性能的内存数据库,具有出色的数据读写能力和持久化支持,可以提供可靠的会话存储和高性能的数据访问能力。 3. 简化配置和集成:shiro-redis-spring-boot-starter提供了封装好的配置和集成方式,减少了我们自己实现集成的复杂性和工作量。 总结来说,shiro-redis-spring-boot-starter为我们提供了一种简化和快速集成Shiro和Redis的方式,使得在Spring Boot应用中实现安全功能变得更加容易和高效。通过它,我们可以实现分布式环境下的会话共享和管理,提供高可用性和性能的数据存取能力,同时简化了配置和集成的复杂性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值