计算机系统应用教程网站

网站首页 > 技术文章 正文

RABBITMQ消费者消失与 JAVA OOM

btikc 2024-09-04 03:11:53 技术文章 10 ℃ 0 评论

原因: 下午先是收到钉钉告警有一个消费者系统任务积压, 当时以为就是有范围上量没有当回事,后来客服群开始反馈说有客户的数据没有生成。这个时候查看mq的后台,发现任务堆积数量还是很多。 这个时候登录一台消费者系统查看日志,发现OOM

[2022-07-09 16:40:34.640] [ERROR] [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-9] [org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.run:1251] 
 - Consumer thread error, thread abort.
java.lang.OutOfMemoryError: Java heap space
        at java.lang.String.<init>(String.java:662)
        at com.alibaba.fastjson.serializer.SerializeWriter.toString(SerializeWriter.java:503)
        at com.alibaba.fastjson.JSON.toJSONString(JSON.java:760)
        at com.alibaba.fastjson.JSON.toJSONString(JSON.java:696)
        at com.alibaba.fastjson.JSON.toJSONString(JSON.java:661)
        at sun.reflect.GeneratedMethodAccessor169.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171)
        at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120)
        at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:50)
        at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:211)
        at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:143)
        at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:132)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1569)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1488)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer$Lambda$976.0000000000000000.invokeListener(Unknown Source)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1476)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1467)
        at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1411)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:958)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:908)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:81)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1279)
        at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1185)
        at java.lang.Thread.run(Thread.java:819)

先看第一个重点:Consumer thread error, thread abort.

从错误中就可以明显看出来,问题的原因:是因为消费线程在执行的过程中,出现内存溢出,导致线程和MQ断开链接。最终导致消息堆积的出现,只要解决内存溢出的问题即可。

OOM的问题排查

线程OOM后打印的文件我们用MAT工具排查(公司使用的JDK是openJ9)

从图像上很明显看出那里占用的大部分内存, 有一个超级大的map,继续分析看看map里的内容是谁。

根据类路径去代码中查询为什么会生成这么多对象。

首先找到在那里使用了这个类

这是logback的类,当时使用这个做日志的打印是想打印这个数据的业务流转日志。 单独输出到一个文件中,方便问题的排查。

知道这个类以后再深入查看一下map数据怎么来的

从这里看到使用了final的map并且在调用write的时候获取helper是调用的computeIfAbsent。

computeIfAbsent()
1、首先会判断map中是否有对应的Key;
2.如果没有对应的Key,则会创建一个满足Value类型的数据结构放到Value的位置中;
3.如果有对应的Key,则会操作该Key对应的Value.

在这里就怀疑是不是因为我程序中每次传递的mapper都是新new的。然后就找我调用的方法。

这个类是我用来logback扩展json字段转换用的。 我在构造JsonGenerator的时候每次都是新new ObjectMapper(), 所以会导致map每次比较的时候发现传递的值是不相同的,会new 一个新的放到Map中。最终导致map变的异常大。

修改很简单

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表