压测并发导报告导致的内存/CPU占用过高问题解决实践

在高并发导出报告场景下,因报告内容过大导致内存和CPU占用过高,通过监控、调整线程池及加入流量控制仍未解决。最终发现特定报告内容异常庞大,修改程序空判断后问题解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

压测并发导报告导致的内存/CPU占用过高问题解决实践

问题背景:

报告导出采用freemarker组件,在多线程环境下工作,自动化测试以25个用户持续发送导出报告请求,请求数量达到500左右时CPU占用1000+,内存几乎吃满。

第一次问题分析:

考虑线程池直接使用 newFixedThreadPool,阻塞队列未设置大小,可能因为线程池堆积任务过多导致,将线程池阻塞队列大小设置为200。

第一次结果验证:

重新进行压测,请求发送至200时线程池拒绝接收,此时一切正常,然而,导出了几十份报告之后,CPU与内存占用率迅速飙升,进程假死,不再向外提供服务。

第二次问题分析:

线程池改为200仍出现问题,依然考虑是数据淤积于线程池导致,但线程池阻塞队列不宜过小,因此,在调用线程池执行导出任务之前加入流量控制器,判断当前系统CPU/内存是否足够空闲,空闲时再发送任务至线程池执行导出。

第二次结果验证:

压测刚开始进程运行平稳,但同样的,导出了几十份报告之后,问题重新出现。

第三次问题分析:

经历过以上两次分析与验证,笔者觉得事情没有那么简单,故而使用同事之前推荐的一款jdk自带jvm分析工具jvisualvm去监控java进程的运行。再次进行压测,发现内存中有一个类的实例数时稳步增加的,怀疑有内存泄漏。通过堆dump、线程dump定位至代码中,发现确实是导出报告线程引用了许多该类的对象。仔细排查代码,并未发现内存泄漏,将代码中该对象在使用之后置为null,重新验证。然而诡异的是,并!没!有!什!么!卵!用!

第四次问题分析:

经过以上几次分析,笔者隐约觉得问题可能并没有那么复杂,于是重启服务,打开jvisualvm监控,发起导出请求之后持续观察监控情况与日志输出。在观察数分钟之后,笔者惊奇地发现,执行生成报告的4个线程均处于活跃状态,但他们应该输出的日志都不动了。观察到这个现象以后,考虑可能是因为到处的某个报告内容太多而占用了很多内存。于是,马上查看该任务id,确认它的内容大小,果不其然,这个任务将mogo知识库中的上千万个组件全部查了出来,那能不GG嘛。而导致这个问题的原因,是程序中空判断,改掉它,重新测试,问题解决!

结论:

分析问题时,要大处着眼,小处着手,免得多走弯路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值