关于collector服务内存溢出异常问题

公司的音频收集服务collector总是不稳定,前几天抛出了内存溢出问题,看了两天的代码,也去现场将jvm的dump文件拷贝出来,由于不稳定的时候服务重启,所以只能对正常运行的服务内存区域做了分析,整体过程如下

先jps查看collector的进程pid

通过pid,使用jmap 的-dump将dump保持到/usr下面。

通过FTP工具从服务器下载dump文件

在本机通过jvisualvm命令打开可视化界面,装入dump文件进行分析,如下



byte[]字节型数组占用了75.7%,打开实例数最高的ConcurrentHashMap,总的实例实际上也是Byte[]。


接着使用jmap -heap pid  查看堆内存使用情况,如下



看到Old Generation使用了将近4G的内存,什么情况下会将对象放置Old Generation中?简单的说明就是Survivor0与Survivor1相互复制切换后,仍然存在(默认是15次据说)的对象将被复制到Old Generation。大家都知道,正常情况下对象的存在时间是非常短的,YGC回收起来是非常的快的,导致YGC无法回收,说明对象一直被强引用,这样只有看看代码了。(期间正好有发生一件凑巧的事情,就是一位同事海潮同学压测雷音过程中,结果压爆了collector服务,我在一旁偷窥了下 jstat -gc 发现FGC执行了2000多次,这让我加深了一些设想)

回去的两天期间,使用本机的collector压测,看看代码(这代码真不好看啊~~),问问亲切的同事们。对于collector有了一定的了解,collector主要是服务于音频采集的分发,其中包括了与阿里引擎和monitor的交互,采集是由客户端agents负责。通过netty长连接的方式不断的向collector发送音频字节数组,每秒32字节(看注释的),collector发送给阿里的字节数根据speend变量,计算公式:32*ms:speed=100ms~250ms,3200~8000。

从上面的分析结果来看,确定是byte[]占用了大量的内存空间,其中ConcurrentHashMap所存储的也是byte[],正好在线程类AsrTask中private Map<Long, byte[]> audioMap = new ConcurrentHashMap<>(); 对应的泛型就是byte[],引起了我们的注意,继续看代码,在run中不断的循环获取LinkedBlockingQueue队列中的byte[],然后再一系列的加工或者等待数据达到3200~8000,再发送给阿里引擎,随后就缓存到audioMap了,也就是说

发送一次缓存一次,100ms~250ms就会触发一次这样的操作,只要没有暂停和停止的命令,通道就会一直有byte[]缓存到audioMap,虽然阿里返回结果的方法onMessageReceived有根据换行和换角色的判断保存音频并且将audioMap清空,但是如果不换行也不换角色的情况下,音频一直无法被YGC,就会被丢到Old Generation中,周而复始Old Generation不断的在增加,最终触发FGC,而这个时候如果采集还未停止,长连接一直保持着,FGC也无法清除这个对象,那FGC将不断的被执行,就会产生STW(2000多次的FGC,STW也是可观的时间吧),由于服务重启,没有异常时段的日志,猜想过去GC不能回收强引用的对象,在高并发的时间段,服务器的内存是相当的吃紧,个人认为产生OutOfMemoryError还是相当有可能的。

另外通道结束后,堆内存没有被GC是因为对象在Old Generation,而Old Generation是需要FGC的,触发FGC需要满足:

1:正确情况下对象创建需要分配的内存是来自于Heap的Eden区域里,当Eden内存不够用的时候,某些情况下会尝试到Old里进行分配(比如说要分配的内存很大,阈值通过JVM:-XX:PretenureSizeThreshold设置 ),如果还是没有分配成功,于是会触发一次ygc的动作,而ygc完成之后会再次尝试分配,如果仍不足以分配此时的内存,那会接着做一次FGC (不过此时的soft reference不会被强制回收),将老生代也回收一下,接着再做一次分配,仍然不够分配那会做一次强制将soft reference也回收的FGC,如果还是不能分配,则抛出OutOfMemoryError。

  参考:JVM源码分析之临门一脚的OutOfMemoryError完全解读

2:system.gc

3:jmap -histo:live

4:jvisualvm 操作gc

5:担保失败

6:Perm空间满








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值