公司业务蒸蒸日上,日订单量暴增, 同事们给都乐坏了,每月奖金多多啊。 奖金是多了,随之而来的麻烦也来了, 这可把我给愁坏了。 伴随着业绩的增长,平台注册用户和在线用户剧增, 网页响应太慢,甚至卡死, 用户的投诉来纷至沓来。
一开始没有找到网页卡的原因在哪里, 重启下应用,速度又上来了, 运行半天后又开始卡了。 老板给了两天时间的解决问题, 解决不了就滚蛋。 还好,最终找到了解决办法,保住了饭碗。解决步骤如下:
首要问题是如何重现生产环境问题,但从哪里可以找这么多用户呢? 手工操作用户登录肯定是不现实的, 最终用性能测试工具的并发用户模拟大用户量并发操作。
一、 高并发下下大量用户登录,模拟session不断创建
使用2000个并发不断请求登录,4分钟后TPS逐步下跌接近为0, 跟生产环境的情况类似,只不过卡死的两现象出现的要快很多。
a.查看日志:HttpsServletRequest.getSession() 出现OOM日志, JVM已经无空间再供Session已经再创建了
b. 查找JVM进程信息: ps -ef | grep java
19619 19603 99 18:08 pts/0 java -classpath /root/apache-maven-3.3.3/boot/plexus-classworlds-2.5.2.jar -Dclassworlds.conf=/root/apache-maven-3.3.3/bin/m2.conf -Dmaven.home=/root/apache-maven-3.3.3 -Dmaven.multiModuleProjectDirectory=/root/app org.codehaus.plexus.classworlds.launcher.Launcher jetty:run
c. 使用jstat命令查看JVM GC 情况: 是什么对象占空间较多呢?
d. dump内存进行分析: Session的实例数超级多,失效时间为1小时,暂时没有办法内存回收,导致JVM一直FGC
session的实例个数为2936926个, 接近300W个,内存不暴才怪 (这里还未考虑业务占用的内存)
二、2000个并发模拟2000个用户登录后做业务性能压测, session个数固定, 每个用户的session数据量不断增大也导致OOM
压测结果:
FGC导致性能测试开始10分钟后TPS下降波动较大
使用命令 jmap -F -histo 20905 发现 UserInfo 实例较多, UserInfo是放在Session中的,Session的失效时间较长导致无法被JVM GC回收
结论:
session在jvm本地大量创建会占用大量内存, session中存放过多对象也将导致内存溢出。 解决办法首先将session中过多的对象迁移出来,只存放用户的ID信息, 减少用户相关的对象放到session中无法被GC回收。 第二步将session迁移到缓存或者DB中存储, 适当的条件下需要调整应用部署架构。
解决问题使用到的性能测试工具
性能测试服务PTS: http://pts.aliyun.com/lite/index.htm
使用文档: https://docs.aliyun.com/?spm=5176.383338.201.106.vZL1xH#/pub/pts
论坛:http://bbs.aliyun.com/thread/243.html