全国统一服务热线

176-0250-1825

新闻中心

当前位置:首页>新闻中心

Java中同步系统溢出问题

问题描述:

这个案例是一个同步系统,负责从一个系统向另一个系统进行数据的同步操作,中间使用kafka中间件进行生产和消费的工作。

有什么问题吗?这是一个OOM的问题,需要手动重启OOM,重启后OOM又出现了,较终Kafka的数据量越来越大,GC的频率越来越高,较终导致系统崩溃。

初步排查:

JVM堆内存溢出只不过是两种情况,要么是在堆内存进行Full GC之后仍然有许多存活对象,要么是突然产生一大堆对象在堆中不能存放而导致OOM的情况下,两者都可能发生。

这种情况在一段时间后就会溢出,同时,同时即使要处理的数据变多也并不是一旦启动就立马溢出,而是OOM的频率变高了而已。

这么看来,可以确认是由于存活对象过多赖在内存里面导致处理数据加载到堆之后老年代又放不下立马就Full GC了,然后Full GC之后发现还是很多对象,较终老年代累积到,结果就只能OOM了。

问题分析:

通过分析,发现Full GC之后对象没有进行回收,当老年代空间为之后,对象无法完成分配较终只能溢出并且停止JVM进程了。

下面我们就来分析一下突然泄露的根本原因,此时需要注意Kafka的消息队列,Kafka是什么,这里不再多说了,它在案例中主要的工作是不断推入两边的数据进行数据的生产消费的同步操作。

重点来了,我们都知道,消费数据可以一次性消费几百条,所以此时就有开发者为了方便消费,把消费的内容设置为了List,并且每一个List有几百条数据。

这种设计结构在消费的时候有什么情况呢?

这里做一个比喻就是传送带上的产品,本来每一道流程的负责人只需要加工传送带上的一份数据,但是使用这个结果就好比在每一份传送带的产品上挂着100多个产品要进行处理!

这种消费无疑是消费不来的,而生产方又在不断地推着数据,较终只能罢工(OOM)。

问题解决:

这是一个典型的生成和消费速率不对等的案例,这里的解决办法就是把队列设置为阻塞队列。

比如设置1024个大小,一旦队列满了,生产方就会停止生成并且阻塞监听这个队列,当队列一旦有空间再开启消费工作,这样消费就可以及时处理,也就不会造成对象积压在堆内存而没办法回收了。


QQ咨询
在线咨询
在线报名
176-0250-1825
176-0250-1825
返回顶部