生产环境中,RabbitMQ 持续积压消息不进行ack ,发生什么了?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 生产环境中,RabbitMQ 持续积压消息不进行ack ,发生什么了?

问题:生产环境 rabbitmq 部分客户端 channel 持续积压消息不进行ack。


0. 服务配置


  • rabbitmq 集群(普通集群模式)


  • 消费者 三台 消费线程各消费者 10


  • 消费者配置 使用 spring-amqp|auto-ack 模式


1. 故障发现


近日有同学发现一个业务队列存在上千个 unacked 消息,并且有持续上涨的趋势。


2. 故障表现


队列下其中两个客户端的各一个 channel 分别阻塞几百条数据,并且在持续累加,重启应用后队列 unacked 消息全部进入 ready 状态等待重消费,但是重启后客户端依然有 channel 重新开始堆积并且在趋势上涨。


3. 问题排查


排查思路


  • 检查 mq 控制台是否是队列创建问题


  • 消费者阻塞是否有规律可循(未ack数据是否有共同特征、阻塞客户端配置是否有问题)


  • 客户端代码是否有问题、应用是否有jvm级别故障


4. 问题定位


经过一番筛查,问题定位到了代码部分,队列消费代码并非刚上线,而是在前一日服务重启后出现的这个问题,重新 review 代码后发现消费者有使用 CountDownLatch 等待多线程消费结果,CountDownLatch#countDown 的调用没有放到 finally 中执行,并且提交到线程池的任务也没有使用 try catch 进行包裹。


到此怀疑是消费线程阻塞到了 CountDownLatch#await 处,异步任务处理时由于偶现异常代码并未执行到 CountDownLatch#countDown 处,再者由于异步任务未捕获异常导致错误直接抛到 jvm 日志无法记录错误。


为了验证这个问题,我们又dump了阻塞服务的栈信息,发现确实有消费者线程阻塞到 CountDownLatch#await 处,问题定位结束。


5. 解决方案


从任务处下手添加 catch 记录日志,并将 CountDownLatch#await 放到 finally 中执行。重启应用再次观察,并未出现 unacked 消息,观察日志也并未出现新添加的 error 日志。


6.问题拓展


同一个 channel 为何会阻塞那么多数据?


线上生产环境采用推模式,rabbitmq 通过 channel 推送消息到客户端,客户端采用 LinkedBlockingQueue 做缓存,一个 channel 对应一个消费者线程,当消费者线程阻塞时 LinkedBlockingQueue 作为中转一直在预存消息,所以会出现很多 unacked 消息。


为什么仅有部分一两个 channel 出现堆积?


线上添加错误日志后实际并未出现错误打印,怀疑之前异常可能是由于重启后第一次请求 rpc 偶现调用失败,猜测暂无法复现,后续需观察日志。


总结


  • 谨慎使用线程同步,谨防线程死锁,务必保证线程不会 hang死。


  • 自建线程池做好错误兜底,不要将异常抛给jvm。


推荐好文


>>【练手项目】基于SpringBoot的ERP系统,自带进销存+财务+生产功能


>>分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!

>>能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
6月前
|
存储 Kubernetes API
K8S上生产环境后,90%都会遇到这个故障
K8S上生产环境后,90%都会遇到这个故障
303 0
|
消息中间件 存储 Kubernetes
k8s1.20版本部署RabbitMQ集群(持久化)——2023.05
k8s1.20版本部署RabbitMQ集群(持久化)——2023.05
681 1
|
11月前
|
弹性计算 资源调度 Kubernetes
Flink三种集群模式,Standalone模式,Flink On YARN,Flink On K8S,这三种模式有啥优缺点,生产环境如何选择呢?
Flink三种集群模式,Standalone模式,Flink On YARN,Flink On K8S,这三种模式有啥优缺点,生产环境如何选择呢?
979 3
|
1月前
|
消息中间件 数据采集 数据库
小说爬虫-02 爬取小说详细内容和章节列表 推送至RabbitMQ 消费ACK确认 Scrapy爬取 SQLite
小说爬虫-02 爬取小说详细内容和章节列表 推送至RabbitMQ 消费ACK确认 Scrapy爬取 SQLite
19 1
|
3月前
|
存储 运维 Kubernetes
在k8S中,生产环境的pv回收策略该如何选择?
在k8S中,生产环境的pv回收策略该如何选择?
|
Kubernetes Devops 容器
生产环境实现k8s多集群管理
生产环境实现k8s多集群管理
|
消息中间件 NoSQL 关系型数据库
【Kubernetes部署Shardingsphere、Mycat、Mysql、Redis、中间件Rocketmq、Rabbitmq、Nacos】
【Kubernetes部署Shardingsphere、Mycat、Mysql、Redis、中间件Rocketmq、Rabbitmq、Nacos】
249 0
|
6月前
|
Kubernetes 网络协议 Python
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(二)
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(二)
190 0
|
6月前
|
Kubernetes 应用服务中间件 开发工具
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(一)
一文教会你,如何通过kubeadm,在生产环境部署K8S高可用集群(一)
1796 0
|
6月前
|
Kubernetes 应用服务中间件 nginx
使用kubeadm搭建生产环境的多master节点k8s高可用集群
使用kubeadm搭建生产环境的多master节点k8s高可用集群
560 0