背景:
oom的项目是在一次上线后发生过两次宕机
使用到的工具 :
mat
查找问题的过程
1:发生第一次宕机后,没发现有问题,于是重启了项目,添加了-XX:+HeapDumpOnOutOfMemoryError
2:过了几天后又发生了这个问题 ,由于上次添加的命令,生成了dump文件
3:使用mat分析dump文件
4:导入后首先看到overview
overview
通过这个图我们可以看出ThreadPoolExecutor占用了956M的内存
由此可以看出应该是线程池出了问题
5:然后点击查看 dominator tree
dominator tree
通过该视图可以看出每个对象与其引用的关系的树状结构,同时包含了占用堆存的大小和百分比
6:然后右键 选择 list objects -> with incoming references
通过这个图可以看出是 utils下的 MessageSender 出的问题
找到这里再去看代码就方便了,直接找到对应的类,然后发送发送方法
可以看到每一次发送都会生成一个task 放到线程池里面去执行,看到这块没问题
然后接着看线程池的生成
问题就在红框这个地方了,可以看到拒绝策略这里,由于消费端消费能力过低,导致阻塞队列呗塞满,后续的触发了拒绝策略,而这块代码可以看出 ,拒绝后调用了 blockingQueue.put()方法,该方法会在容量满了以后进行阻塞,久而久之堆积的对象越来越多,导致oom
由于我们这个发送的是日志,有些类型的日志是不需要的
解决方法:
1:过滤掉不需要的日志,减少发送量
2:消费端优化代码,增加机器,提高消费能力
3:修改拒绝策略,保证不会因为消费慢而宕机