一次异步写入kafka导致的伪内存泄漏

    对应用进行压测,刚开始几分钟tps很高能达到3000,压了八分钟后忽然降到了400多,十分奇怪,top看了一下cpu飙到了700%多。用JvisualVM连接上JVM进行监控,发现内存使用率高达90%多,然后在疯狂GC,但是内存却释放不了。心中十分奇怪,难道是内存泄露了?于是查看内存信息,发现了大量HashMap.Node和char[]对象在内存中。几乎占了70%内存,查看日志却无异常。

    一时间毫无头绪,程序就是接受前端请求,然后http请求后台获取结果再返回即可,然后会将请求信息包装成runnable任务提交给一个异步线程池,写入kafka。之前测试也没出现过这种问题,怎么就内存泄漏了呢?仔细分析代码中创建了hashMap的地方,怎么也不应该无法GC回收啊。偶然发现,kafka里貌似没有收到生产者消息,难道是因为异步发送kafka的问题?

    发送kafka的任务也没打印日志,无法跟踪,然后采用的一个fixedThreadPool去执行,如果发送kafka有问题的话,有可能任务会一直堵塞在线程池的阻塞队列中,而且这是一个无界队列,越塞越多导致占满内存。于是修改代码:

1、发送任务打印失败异常日志,方便跟踪

2、采用threadpoolexecutor创建一个线程池,queuesize设置为10W,防止任务积压把内存撑爆

3、把日志级别调成debug,方便查询问题

重新打包部署,再次测试,查看日志,发送kafka报错,连接不上leader直到60s超时,这就难怪了,线程都阻塞在这60s上了,队列中任务越积越多,终于撑满了内存。把kafka修好,再开始压,神奇都事情出现了,内存不涨了,tps降到了400,查看gc并不频繁,这又是闹哪出?

top -Hp pid随便找了一个占用cpu较高都线程,strace -cp tid看看这线程都干了啥,发现99%的时间在mutex上,完了,这是在争抢互斥锁,我代码里没用锁啊???

灵光一现,难道debug模式打印日志太多,N多业务线程争抢一个日志文件的reentrantlock锁去写日志,导致锁竞争了?调成info再试,tps重回3000!

当然,若是应用确实需要打印大量日志,可以优化:

  • 异步日志,但是会存在断电或者日志队列溢出丢失的可能
  • 远程日志,日志放入外部消息队列,保证持久化,但需额外部署日志存储队列
  • 多线程日志,按线程(或线程取模)记录日志,减少竞争,日志也能保证持久化

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值