Java_内存泄漏_实例1
来源:互联网 发布:达特康票务网络系统 编辑:程序博客网 时间:2024/06/01 08:10
版权声明:本文为博主原创文章,未经博主允许不得转载。
记一次压测时Java内存泄漏问题的发现过程(2017-08-14)
【前篇】
①20170811进行A系统与B系统之间的会话功能进行压测,加上脚本准备期间的聊天消息,预计累计聊天30w+条消息;
②20170814原计划加大量对会话功能进行压测,情况如下;
【应用表现】
①B系统前台打开报错“504”;
②查看后台应用CPU情况,CPU利用率高达700+%(8核);
③查看后台内存情况,持续FullGC,且一次FullGC的时长在9s左右,从这里可以粗略定位CPU高的原因是内存GC问题导致;
【查看应用JVM配置】
①请教B开发团队,loader提到应该不是JVM配置引起的问题;
【尝试进行分析】
①尝试使用jvisualvm进行“堆 dump”,但是因为没有内存了所以jvisualvm连接后卡死(之前测试可以正确连接并显示JVM情况);
②使用jmap命令“jmap -dump:format=b,file=heap.hprof pid”进行dump,dump文件有16G(无奈使用mat打不开);
③尝试shutdown应用后重启,无法shutdown;最后使用“kill -9 pid”暴力解决无法shutdown的情况,后重启应用;
【重启后情况】
①使用jvisualvm查看堆内存使用情况,表现为“堆内存持续上升”;
②重启1小时后,dump文件进行分析,其中“java.util.concurrent.LinkedBlockingQueue$Node”占用内存高达1G,基本可以判断存在“内存泄漏”;
“com.best.oasis.B.common.entity.messageTransship.MessageTransship”对象151MB,且有160w个MessageTransship对象;
③B开发Review代码:原因所在:线程池中等待执行的任务队列存在内存泄漏的问题;
正常情况:
A应用服务器发送消息给B服务器后,B服务器接收消息后将该消息存于中间表B_messagetransship中,同时将该消息转发给B客服端,B客服端接收消息并对该条消息进行ack,ack成功后删除B_messagetransship中的该条消息。为了防止消息丢失,B有一个定时重发job,用于每隔5s将B_messagetransship表中的消息再次推送一次;
异常情况:
1.A服务器发送给B服务器的消息存在于B_messagetransship表中后(此时状态为“PENDING_SEND”),因为网络/B客户主动退出等问题,致使B客户端并未收到来自B服务器的该消息,则该消息的状态被置为“SEND_FAILED”存在表B_messagetransship中;
2.A服务器发送给B服务器的消息,B客服端正确收到,但是B客服端发送的ACK请求返回失败,则该消息的状态被置为“PENDING_ACK”存在表B_messagetransship中;
失败消息定时重发实现逻辑:
每隔5s从B_messagetransship中逐个取出失败的消息记录,以链式队列的形式链接在等待执行的任务队列中,若5s内该消息被线程处理且推送状态为成功,则删除数据库表中该消息记录;若5s内该消息被线程处理但推送状态为失败,则数据库表中的该条消息记录保持不变;若5s内该消息并未来得及被线程处理,下一次定时重发任务触发时,该消息会保留第二个拷贝在待处理任务队列中,以此类推;
bug发现的诱因:
B_messagetransship表失败推送的消息量比较大,B_messagetransship表11w+条数据,失败消息量大的原因:
①11907条“再见”,状态为:SEND_FAILED
产生原因:B客户端对话完毕未接收到再见语,就发起了“{"type":"close","sid":"${sid}"}”的请求,该现象在实际中也可能产生;
②17120条“很高兴为您服务”,状态为:PENDING_ACK
产生原因:压测脚本未对“很高兴为您服务”消息进行ack;
③剩余的8w+条,为A发送给B的对话消息,推测是在脚本准备期间产生的数据;
开发下期优化思路:
①为B_messagetransship表中的消息增加生存时长,若超时则直接删除;
②限制待执行任务队列中messageTransship对象的数量,达到一定个数则不再从B_messagetransship中获取;
测试脚本修改:
①增加对“开始语”与“结束语”消息的ack;
- Java_内存泄漏_实例1
- Java_编程实例_需求一
- Java_编程实例_需求二
- Java_编程实例_需求三
- Java_编程实例_需求四
- Android内存泄漏分析实例
- Android内存泄漏分析实例
- C++学习总结_防止内存泄漏
- 85_线程导致的内存泄漏
- java_内存
- Java_内存
- Java_面向对象(1)_续
- osgviewerMFC实例中内存泄漏严重问题
- 对于handler内存泄漏分析解决+实例
- MongoCollection::find 内存泄漏以及规实例
- 12.4.1 内存泄漏
- android内存泄漏-1
- Android内存优化七:MAT具体分析内存泄漏实例1
- LibZXing二维码扫描/生成库,基于ZXing最新版3.3的封装
- Oracle数据库中的分页 按工资由高到低 每页pageSize条记录
- 单向链表逆序
- Arrays工具类源码的剖析
- Java NIO Files
- Java_内存泄漏_实例1
- Linux常用命令小结
- 第一次Filter过滤器的简单使用总结(一)
- Jquery的基本入门
- 算法提高 判断名次
- Linux 输出重定向>和>>的区别
- Redis设实
- 学习日记16
- MyBatis与MyBatis-Spring中的部分接口说明