# 大量数据库查询导致内存溢出
# 问题现象
用户正在做压力测试,模拟500个人登录,测试系统性健康度。
压测过程中从系统监控发现内存持续上升直至100%,随后系统卡住一段时间,卡顿恢复后内存降至20%,需要分析内存持续上升原因。
通过系统管理员登录,查看系统监控,年老代的内存占用,可以发现持续上涨:
最高会到100%,随后系统卡住,进行full gc:
系统自动gc后,内存占用又降低到20%,同时看gc次数可以看到非常高,可以判断服务器一直存在:涨内存到100%->full gc->降低到20%左右->涨内存...循环操作。
# 分析过程
内存溢出需要分析内存文件,看中间件是否自动生成,如果没有就自行jmap导出。
导出的文件通过MemoryAnalyzer工具 (opens new window)进行分析。
通过分析工具发现,占用内存最大的是WorkThread,内钻分析这个Thread是一个个请求,初步可以怀疑:是客户端发送了很多请求到服务器,每个请求都在进行运算并且占用大量内存。
上一步确认是请求多,并且每个请求占用大量内存,没有找到源头,下一步是分析内存占满时有哪些线程堆栈,看谁问题最突出。
在内存分析机器上,找到.threads的文件,通过此文件检查线程执行情况:
最后通过堆栈分析,登陆堆栈StringUtil.passwordBlacklist存在大量卡在数据库查询的动作,并且出现了374次。了解到数据库查询的表有27万数据,如果全部拉取到内存中就会导致每个线程都占用大量内存而溢出。
# 解决方案
了解到这个是定制开发功能,客开进行代码优化,比如: 将数据缓存到内存中,通过内存判断数据;或者增加索引+优化SQL,让查询达到毫秒级。
创建人:het
修改人:het