zoukankan      html  css  js  c++  java
  • Java_内存泄漏_实例1

      版权声明:本文为博主原创文章,转载请注明出处。 


      记一次压测时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;

  • 相关阅读:
    sqlserver2008 数据库中查询存储过程的的创建修改和执行时间,以及比较常见的系统视图和存储过程
    ASP.NET MVC 处理管线模型
    C# 四舍五入中一处易错点
    vs 快速定位文件
    动态调试JS脚本文件:(JS源映射
    EF Code First中的主外键约定和一对一、一对多关系的实现
    ws-trust、域、webservice接口的总结
    设计模式(三)装饰者模式
    设计模式(二)观察者模式
    设计模式系列(一) 策略模式
  • 原文地址:https://www.cnblogs.com/xpp142857/p/7375217.html
Copyright © 2011-2022 走看看