线程堵塞(挂起)导致消息队列消息挤压

news2024/10/6 14:35:52

一、背景

A服务作为生产者,每天发送上百万的mq消息,每一个消息包含500个用户id数据。

B服务作为消费者,接受MQ消息并通过http调用第三方请求进行业务处理,消费组使用了rabbitmq

的多线程消费组,一个实例并发40个mq消费者线程,每个线程一次获取10个消息进行消费

Mq消费者配置如下
  rabbitmq:
    connection-timeout: 2000
    cache:
      channel:
        size: 100
    # 消息发到rabbitmq-broker-cluster回调
    publisher-confirms: true
    # 交换机将消息投递至队列失败时回调
    publisher-returns: true
    listener:
      # 手动确认消息已被消费
      simple:
        acknowledge-mode: manual
        # consumer的并发数
        concurrency: 40
        max-concurrency: 50
        # 每个消息者每次取多少数据
        prefetch: 10

Mq挤压消息如下

二、排查

 排查思路1

找出rabbitmq挤压的消息,在本地模拟消费,找出没有进行消息确认的原因,通过rabbitmq控制台的Get messages功能

复制payload的消息进行base64转码,转出来的消息是乱码不完整的,怀疑

是rabbitmq还结合了其他加密处理,放弃这种排查思路

排查思路2

rabbitmq的unack消息挤压,那就是消费者没有进行ack确认,怀疑消费者代码有异常导致没能执行到ack的代码。

查询服务器日志,没发现有报错的日志,

梳理业务代码,消费者使用了spring aop around机制进行消息确认,所以不管代码有没有报错,按理说都会手动进行mq消息ack确认

排查思路3

服务器应用没有挂掉

消费组数量是符合配置大小

怀疑是线程挂起,不执行消息确认代码导致消息的挤压

进行排查应用线程,通过jstack命令导出jvm线程

使用IBM的TMDA工具进行分析线程堆栈

工具下载地址:https://publib.boulder.ibm.com/httpserv/cookbook/Major_Tools-IBM_Thread_and_Monitor_Dump_Analyzer_TMDA.html 

三、线程堆栈分析

TMDA分析如下

通过分析图,看到大量park线程,确实是符合现状,应用的线程挂起了

通过stack深度高到底排序,业务代码存在线程等待情况,具体代码CountDownLatch.await

四、业务代码分析

通过上图stack提示,找到关联的业务代码

伪代码如下:

// new一个CompletableFuture
public CompletableFuture<Integer> httpCall(String tokenData){
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            long time = 3000L;
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return Integer.parseInt(tokenData);
        });
        return completableFuture;
    }

httpCall(tokenData).whenCompleteAsync((returnValue, ex)->{
		// do business
		// ex.getMessage()
		// 其中ex对象为空,使用ex.getMessage()报了空指针,导致没能执行如下的countDown
		countDownLatch.countDown();
	})

消费者通过http调用第三方服务,为了提高并发,使用了多线程,每一组(数十个为一组)http请求批次调用完成后再把请求响应结果存入数据库。

主线程使用了countDownLatch.await进行等待。

其中whenCompleteAsync方法存在空指针问题,导致没能执行如下的countDown。

这里有人会问不是说日志没有空指针异常吗

对,子线程报了空指针,因为CompletableFuture执行每次都是new 一个新的CompletableFuture对象,并把结果作为下一个CompletableFuture执行的入参,通过伪代码可以发现,执行whenCompleteAsync后,没有新的CompletableFuture方法执行,所以异常没有抛出来,使得排查变得困难

五、解决

因为存在whenCompleteAsync报错的情况,添加多一个新的处理方法,捕获异常也进行

countDown的操作

代码如下:

httpCall(tokenData).whenCompleteAsync((returnValue, ex)->{
		// do business
		// ex.getMessage()
		// 其中ex对象为空,使用ex.getMessage()报了空指针,导致没能执行如下的countDown
		countDownLatch.countDown();
	}).exceptionally(e ->{
                log.info("exceptionally捕获到异常,tokenData={}, e={}", tokenData, e.getMessage());
                countDownLatch.countDown();
                return null;
            })

六、结论

1: 熟练CompletableFuture的使用,要看源码的实现(实现原理cas + 多个future采用入stack,每次把前一个future的结果作为参数传入下一个future去执行)

2:使用多线程需要考虑异常、超时等情况

3:熟练使用jvm stack分析工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/633185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四种Bootloader程序安全机制设计

正文 大家周末好&#xff0c;我是bug菌~ 不管是玩单片机还是嵌入式linux&#xff0c;基本上都会接触到bootloader&#xff0c;所以bootloader程序也是一个关键的组件&#xff0c;进行硬件初始化&#xff0c;应用程序的合法性、完成性检测、升级功能等等都与其息息相关。 像一些…

【ABAP】数据类型(二)「预定义数据类型」

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后端的开发语言A…

【哈希的模拟实现】

文章目录 1 哈希概念2 哈希冲突2.1 直接定址法 (常用)2.2 除留余数法 (常用)2.3 平方取中法2.4 折叠法2.5 随机数法2.6 数学分析法 3 闭散列3.1 线性探测3.2 二次探测 4 开散列4.1 开散列概念4.2哈希桶的模拟实现4.3 开散列与闭散列的比较 1 哈希概念 顺序结构以及平衡树中&…

Science|改变微生物群落可以增强树木对气候变化的耐受性

改变微生物群落可以增强树木对气候变化的耐受性 Shifting microbial communities can enhance tree tolerance to changing climates Research Article&#xff0c;2023-5-25&#xff0c;Science&#xff0c; [IF 63.714] DOI&#xff1a;10.1126/science.adf202 第一作者&…

Java常用快捷键

在编写java代码时&#xff0c;要提升自己的编写代码的速度&#xff0c;光是靠鼠标来完成各种的操作是不行的&#xff0c;还会显得十分不成熟&#xff0c;所以这是就需要我们使用一定的快捷键&#xff0c;在键盘点击之间&#xff0c;完成代码的操作。接下来我就为大家介绍常用的…

7.2DIY可视化后台表格自定义列显示类型

后台表格自定义列显示类型 本教程均在第一节中项目启动下操作 后台表格自定义列显示类型前言一、图片格式内容显示:二. 效果展示: http://localhost:9999/#/hdp三:自定义列使用:1.添加字段:自定义列,取值自幻灯片title2. 设置自定义信息: 三.效果展示本文章原自bilibli作者视频…

6月6日复盘总结 11H10min-|23:15~23:25*

​​​​​​​ 7:20-8:20 背书翻译单词 【1h】 8:30-9:00 乐词 【30min】 9:00-10:00 TPO66 L1 精听 【1h】 10:00-10:30 TPO66 L1 错题分析 【30min】 10:30-11:30 L2 Fish Movement 精听 【1h】 11:40-12:40 午饭+水果🍑+玩手机…

【华为OD统一考试B卷 | 100分】经典屏保(C++ Java JavaScript Python)

题目描述 DVD机在视频输出时,为了保护电视显像管,在待机状态会显示“屏保动画”,如下图所示,DVD Logo在屏幕内来回运动,碰到边缘会反弹。 请根据如下要求,实现屏保Logo坐标的计算算法。 屏幕是一个800*600像素的矩形,规定屏幕的左上角点坐标原点,沿横边向右方向为X轴…

jeecg-boot权限篇

前言 本文档是对jeecg-boot官方文档的一个分析和补充&#xff0c;具体的可以同时互相参照来看&#xff0c;难免个人理解有出路&#xff0c;如有错误&#xff0c;还望补充和指正&#xff5e; 文章目录 角色、用户、部门普通权限控制特殊定制化权限按钮控制文本输入禁用 列表控制…

碳中和城市建筑能源系统(2):网络篇(龙惟定)2022

碳中和城市建筑能源系统(2):网络篇 摘要 本文是碳中和城市建筑能源系统系列文章的第二篇,分别概要介绍了城市能源系统中的电网、热网和燃气网在碳中和背景下的新概念、新技术及新方法。强调未来的能源网以电网为主,三网融通,构成城区的能源互联网。综述了智能电网的灵活性、热…

我们不会很快有GPT-5;让 ChatGPT 帮我们总结 Hacker News

&#x1f989; AI新闻 &#x1f680; OpenAI联合创始人Sam Altman&#xff1a;我们不会很快有GPT-5 摘要&#xff1a;在2023北京智源大会的“AI安全与对齐”主题论坛上&#xff0c;OpenAI联合创始人Sam Altman表示&#xff0c;目前他们没有答案&#xff0c;不会很快有GPT-5&a…

OpenCV 项目开发实战--对图像种的斑点进行检测(Python、C++代码实现)

什么是斑点? Blob 是图像中一组连接的像素,它们共享一些共同的属性(例如,灰度值)。在上图中,暗连接区域是斑点,斑点检测旨在识别和标记这些区域。 文末附相关测试代码的下载链接 SimpleBlobDetector 示例 OpenCV 提供了一种基于不同特征检测和过滤斑点的便捷方法。让…

es相关的知识点

海量数据下如何提升es的操作性能 .filesystemcache os cache操作系统缓存 es中的数据,实际上写入磁盘,磁盘文件的操作系统,实际上会将数据写入到oscache中 es的搜索引擎严重依赖于底层的filesystemcache 如果filesystemcache的内存足够大,可以容纳所有的index segmentfile索引…

Mac环境下在vs code中配置copilot

1、下载vs code编辑器 2、在GitHub个人设置里&#xff0c;把copilot设为allow&#xff0c;这里涉及要开通服务就不再详述。 3、在vs code插件市场里下载GitHub copilot 安装好了以后根据指示输入你的GitHub账号即可 编译器底部出现copilot图标即表示安装成功 使用方法就是你先…

GD32F4单片机实现接收超时中断+DMA实现串口的不定长接收和DMA发送

1、通常的实现方式介绍 环形缓冲区定时器超时中断的方式 优点 环形缓冲区可以接收多帧数据数据帧超时间隔可以设置 缺点 设备任务比较繁重时&#xff0c;使用中断接收可能会丢失数据。尤其是在长时间关闭中断或者串口中断优先级不高时频繁进出中断。在使用RTOS的系统中&#x…

给第一行单元格赋值 + WPS JS获取工作表的总行数 + WPS JS获取工作表的总行数

戳我&#xff0c;了解更多相关办公的小技巧 给第一行单元格赋值 1、在计算机中有一种ASCII编码&#xff0c;其中A在计算机中的表示的数字是65&#xff0c;a的ascii码是97&#xff0c;b的ascii码是98。 2、从A1到F1可以看到第一个字母在变化&#xff0c;第2个数字始终是1&#x…

过电流保护原理

过电流保护是指当电流超过预定最⼤值时&#xff0c;使保护装置动作的⼀种保护⽅式。当流过被保护原件中的电流超过预先整定 的某个数值时&#xff0c;保护装置启动&#xff0c;并⽤时限保证动作的选择性&#xff0c;使断路器跳闸或给出报警信号。 过电流保护主要包括短路保护和…

北京通信展的精华内容,都在这里!(上篇)

友情提醒&#xff1a;本文图片较多&#xff0c;请大家注意手机流量。 大家好&#xff0c;我是小枣君。 昨天&#xff0c;中国国际信息通信展览会&#xff08;PT展&#xff09;在北京正式落幕了。 小枣君全程参加了这场行业盛会。按照惯例&#xff0c;我来给大家汇报一下现场的情…

ChatGPT Prompt 提示词设计技巧必知必会

本文内容整理自图灵社区直播《朱立成&#xff1a;ChatGPT Prompt提示词技巧必知必会》。 朱立成&#xff0c;图灵社区《ChatGPT即学即用》视频课程作者&#xff0c;软件工程师&#xff0c;对新事物充满好奇&#xff0c;关注ChatGPT应用。2001年毕业于浙江大学&#xff0c;从事软…

硬件设计电源系列文章-电路电源设计流程

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 本文主要介绍硬件单板电源设计流程。 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 主要分三部&#xff1a; 电源需求&#xff1a; 根据硬件总体方案&#xff0c;确定各芯片所需的供电电压&#xff1…