首页 > 其他分享 >解决了这次的消息队列堆积事故,我又解锁了新的认知与思考...

解决了这次的消息队列堆积事故,我又解锁了新的认知与思考...

时间:2024-04-20 12:23:03浏览次数:35  
标签:... 消费者 队列 解锁 线程 工单 邮件 堆积

大家好,我是程序员陶朱公。

前言

前两天解决了一个线上消息队列堆积事故,在这里做一个复盘与总结,希望我解决问题的方式、方法、手段对你将来遇到类似的事情有一定的帮助与启发。

背景

前两天,有业务方反馈,他们日常处理的工单数据变少了,希望开发同学去排查一下原因。

这里简单的画下我们系统的一个逻辑架构图:

逻辑架构图

在消费者应用前,有一个专门拉取邮件的服务,拉取邮件收件箱的邮件后,会将邮件存储在本地数据库作为原始邮件进行保存,保存成功后,会将保存下来的messageId,发送到MQ中去,供下游消费者应用消费。

像之前功能正常,消费者应用会从MQ中解析拿到MessageId,然后解析这封邮件,生成对应的工单。但一旦消费者应用由于各种原因消费不动了之后,就会造成队列消息的堆积。

分析

既然说到了堆积,我们就需要了解一下,堆积的整体情况:

消息队列堆积图

可能有小伙伴觉得说,这个对接的数字不是很大呀,业务方这么敏感吗。这里我想简单表达一下,敏感度这个事情主要还是看具体业务,case by case来分析。像我们的业务,相关操作人员每天都要及时处理邮箱里客户反馈的内容,需要及时与客户暂开沟通,而且每一天对这个工单的处理量,也是他们的考核指标,如果由于系统原因,导致他们不能及时处理本该生成的工单,影响面很大。

OK既然是消息对接,如果这方面实战经验比较欠缺,但八股文背的苦瓜烂熟的小伙伴,第一意识可能从脑海中会蹦出来一个认知,是不是消费者应用自身性能问题,比如CPU100%啊、FULLGC啊等造成消费者线程没有资源进行调度、处理。

这个认知肯定是没错的,我第一时间,也是照这这个思路去看了一下线上监控大图,观察后发现,上述关心的一些列指标在线上都是正常不过的,CPU负载不高,内存够用,没有FULLGC等情况发生。

那还能是什么原因造成堆积了呢?如果是你,此刻,你会怎么继续排查呢,欢迎大家把各自的想法或思路,在评论区输出参与讨论。

这里分享一下我的排查思路。

其实也是很容易就联想到的即一定是固定数量的消费者线程不明所以被Hang死了,而且是出不来的那种,导致没办法继续处理队列里的数据。

消费者线程配置参数

上图是我们配置的消费者线程参数,用了两个线程来消费队列里的数据。如果两个线程都Hang死了,那绝B是会造成队列堆积的。

所以,我们有必要去堆栈里面,看看这两个消费者线程的整体情况。

怎么看呢?

有很多手段,比如jstack 线程ID或借助一些开源工具,比如阿里的Arthas。可以用Arthas列出所有线程

然后找出你的消费者线程ID,最后执行thread id就可以查看线程的堆栈情况。

当然如果你们的PASS平台或一些云应用,查看对接的线程,会更方便,像阿里云平台上就可以直接查看:

点击堆栈查看按钮后,我们按下里面的内容长啥样:

消费者线程堆栈内部情况

我截图的内容,正式消费者线程内部情况的表现。很明显,我框的类的方法有问题,导致了线程一直Hang在了那里出不来。后来定位到了相关代码,发现内部其实做了一件事情,就是将一个URL地址,一个在线的PDF地址,然后在pdfToPng方法内部,会流的形式解析生成本地图片进行保存,遇到一些特别大的PDF源文件,就长时间出不来了。

而且我也看了原来的代码,这代码URL链接出,居然都没设置超时时间这一个选项,如果遇到长时间的这种IO操作,那消费者线程不Hang死才怪。

解决方案

既然知道了问题的症结,那就不难处理,就像上图所示,在pdfTopng方法内部,加上超时时间设置,后来用几天时间观察了一下线上的数据,发现还是有效的。

结论

今天跟大家分享了一下,我前端时间遇到的一个线上消息队列堆积的事故,也跟大家详细阐述了,我遇到问题一步一步是如何分析、排查问题的,最后也给出了我修复问题的解决方案,希望大家喜欢。

 

写到最后

感谢您一路陪伴着我,探索编程的奇妙世界。如果您对程序员职场进阶窍门、编程技巧和计算机原理等充满兴趣,那么不要错过未来我为大家奉上的精彩内容!点击关注,让您的程序员之旅更加丰富多彩,我们一同成长,一同前行!

标签:...,消费者,队列,解锁,线程,工单,邮件,堆积
From: https://www.cnblogs.com/StarbucksBoy/p/18147554

相关文章

  • 优先队列
    priority_queue默认大顶堆小顶堆includeincludeusingnamespacestd;voidmax_k_num(){intsource_data[10]={3,5,8,1,10,2,9,15,13,16};intk=5;//小根堆priority_queue<int,vector,greater>q;for(auton:source_data){if(q.size()==k){......
  • 高并发(阻塞队列)
    阻塞队列是一种常用的并发编程工具,它能够在多线程环境下提供一种安全而高效的数据传输机制阻塞队列是一种特殊的队列,它具有以下几个特点:1、阻塞特性:当队列为空时,从队列中获取元素的操作将会被阻塞,直到队列中有新的元素被添加;当队列已满时,向队列中添加元素的操作将会被阻塞,直到队......
  • 队列
    队列目录队列LinkedBlockingQueue阻塞队列SynchronousQueue交换队列DelayQueue延时队列ArrayBlockingQueue有界循环队列常见面试题LinkedBlockingQueue阻塞队列新增操作add队列满的时候抛出异常offer队列满的时候返回false查看并删除remove队列空的时候抛出异常......
  • mysql锁表解锁
    锁表语句LOCKTABLEStbl_nameREAD;锁表怎么解决?MySQL锁表怎么解锁?#1.查进程,主要是查找被锁表的那个进程的IDSHOWPROCESSLIST;#2.kill掉锁表的进程IDKILL10866;//后面的数字是进程的ID====================--锁表解决方法showfullprocesslist;--显示完整......
  • 通义灵码×西安交通大学携手打造“云工开物-高校训练营”,解锁 AI 时代编程学习与实战
    作为大学生如何利用AI“整活儿”?欢迎各位同学关注阿里云与西安交通大学计算机学院携手打造的“云工开物-高校训练营”,带你走近AI编程助手“通义灵码”。通义灵码是阿里推出的免费AI编程工具,拥有实时代码续写与优化、自然语言生成代码、单元测试生成、代码注释生成、代码解释......
  • oracle 解锁和密码重置
    通过登录服务器的命令行工具首先,管理员需要登录服务器的命令行工具,执行以下命令:sqlplus/nolog这将启动SQL*Plus工具,即可以通过该工具连接Oracle数据库。在SQL*Plus中,管理员应该输入以下命令:connect/assysdba进行用户解锁,执行以下命令:ALTERUSERuser_nameACC......
  • 阿里云消息队列升级全新品牌 ApsaraMQ丨阿里云云原生 3 月产品月报
    云原生月度动态云原生是企业数字创新的最短路径。《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供数字化的路径与指南。趋势热点......
  • 队列-优先级队列
    队列-优先级队列1.定义:优先级队列是一种特殊的队列,其中每个元素都有一定的优先级。元素的出队顺序是根据它们的优先级决定的,而不是它们被加入队列的顺序。高优先级的元素会先于低优先级的元素出队。2.实现方式:优先级队列通常通过堆(特别是二叉堆)来实现,以保证高效的元素插入和......
  • 数据结构-队列
    数据结构-队列1.定义:队列是一种遵循先进先出(FIFO,FirstInFirstOut)原则的线性数据结构。在队列中,元素从一端添加(队尾),从另一端移除(队头)。classQueue:def__init__(self):self.items=[]主要操作:队列的主要操作包括enqueue(向队尾添加元素)、dequeue(从队头......
  • JDK11下的优先级队列小问题
    优先级队列中存了我自定义的对象,比较规则写好了,存完了之后我去修改堆中对象的值(比较器中写的值),发现堆没有即刻相应调整,导致结果不对但是每次我让堆中出一个,再进一个堆就调整好了暂时不知道什么原因,猜测可能是堆中存对象的话需要改动才会调整。......