RabbitMQ消费者为何会突然神秘消失,排查方法有哪些?
摘要:开心一刻 今天好哥们找我借钱哥们:兄弟,我最近手头紧,能不能借我点...我:我手头也不宽裕,要不你试试银行贷款或者花呗?哥们:不行,那个借了要还的我:... 问题回顾 某天下午,生产监控告警:消息积压,队列 xxx 消息数超过 100;我第
开心一刻
今天好哥们找我借钱
哥们:兄弟,我最近手头紧,能不能借我点...
我:我手头也不宽裕,要不你试试银行贷款或者花呗?
哥们:不行,那个借了要还的
我:...
问题回顾
某天下午,生产监控告警:消息积压,队列 xxx 消息数超过 100;我第一时间想到的是应用服务是不是停了,但应用服务存活监控又没有告警,但我还是找值班运维同事帮忙确认了下,确认结果是服务的 6 个节点都是存活的,然后我又让运维确认了下队列的消费者情况,结果发现消费者列表中只有 2 个节点的消费者,其他 4 个节点的消费者不见了,所以消息消费不过来,导致了消息积压!
所以问题来了
那 4 个节点的注册的消费者为何消失?
但当务之急是解决消息积压的问题,所以让运维重启那 4 个节点的服务,消费者重新注册上,消息得以快速消费,消息积压告警得以恢复
生产问题虽暂时得以解决,但未找到根因,还是存在复发风险;下面就请大家跟随我的脚步,来看看我是如何排查的
问题排查
直接查 ERROR 级别的日志,很容易就能就找到了关键日志
Consumer thread error, thread abort.
以及异常堆栈
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at java.lang.StringCoding$StringEncoder.encode(StringCoding.java:300)
at java.lang.StringCoding.encode(StringCoding.java:344)
at java.lang.String.getBytes(String.java:918)
...
Consumer thread error, thread abort 大家能看懂吧,就是字面意思
消费者线程错误,线程终止
消费者线程就是我们前面提到的队列消费者,一个队列消费者就是一个消费者线程,消费者线程终止那就意味着队列消费者终止,也就对应文章标题中的 消费者消失;是不是离真相越来越近了?
OutOfMemoryError 是不是很熟悉,内存溢出嘛
OutOfMemoryError 表示 Java 虚拟机在堆内存中没有足够的空间来分配对象
问你们一个问题:OOM 一定会导致 JVM 退出吗,这个问题你们先思考,后面答案会揭晓
回到正题,从关键日志以及异常堆栈,我们是不是可以得出以下推测
OOM 会导致消费者线程终止
有了推测,那就去验证呗;我先给大家模拟下案例,基于 SpringBoot,pom.xml 关键依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
配置文件 application.yml
server:
port: 8088
spring:
rabbitmq:
host: 192.168.2.118
port: 5672
username: admin
password: admin
virtual-host: /
listener:
simple:
acknowledge-mode: manual #设置确认模式手工确认
concurrency: 3 #消费者个数,线程个数
prefetch: 1
RabbitMQ 配置 TaskRabbitConfig.java
package com.qsl.rabbit.config;
import com.qsl.rabbit.constant.Constant;
import com.qsl.rabbit.listener.TaskMessageListener;
import org.springframework.am
