一次消息队列堆积问题排查,我把坑踩了个遍!官网介绍
一.背景
该问题涉及的系统环节如上图所示,每个系统的基本职责是:
代理:提供请求代理服务。统一通过代理发送给下游系统的各种请求,使上游系统不需要知道下游服务使用的差异;同时提供限流、导流等精细化服务特性;Latour SDK:为所有存储平台提供统一的映像下载功能。
它通常与图像算法模型串联布置;预测引擎:提供模型推理服务。支持各种机器学习和深度学习算法模型的工程化部署;
二、故障排除:本文使用的消息队列内部称为MetaQ,外部开源版本为RocketMQ,以下简称为“MQ”。1.问题描述:某天早上收到报警通知,提示代理系统入口MQ堆积。
当我打开控制台时,我发现500台代理机器中有一台严重堆积,而其他机器运行正常:
2.一句话,根本原因我们开门见山,直接说问题的根本原因(详细调查过程请参考以下内容):
个别机器堆积:有一个消耗线程卡在这台机器上,虽然其他线程正常消耗,但MQ机制确定消耗站点不前进;HTTP下载卡住:使用的HttpClient版本存在bug,超时在特定情况下不会生效。
可能导致线程一直被卡住;3.故障排除过程1)本机的消耗速度是否太慢?第一反应是这台机器的消耗太慢了。其他机器可以快速消化相同数量的新闻,但由于消费缓慢,新闻一直在堆积。但是,在MQ控制台中进行详细比较后,
发现该机器的业务处理时间和TPS消耗与其他机器相似,并且不同机器的规格相同:
其次,观察阿尔萨斯绘制的火焰图,右边两个细长的火焰是我们系统的业务逻辑(火焰更高是因为RPC的调用堆栈更深)。从图中可以看出,火焰图中没有明显的“平顶效应”,火焰的宽度相对较窄。
也可以说明机器在执行业务逻辑时没有明显的耗时症结,这也可以证明机器没有因业务处理缓慢而堆积:
2)系统指标是否正常?登录机器,发现CPU、MEM和负载都正常,接近正常机器,没有发现明显的线索:
并且该机器没有明显的全GC:
3)限流引起的?提示:代理请求时代理会限制流量机制,超过限制的流量会触发阻塞等待,从而保护下游同步服务。因此,如果今天的系统流量很大,超过了下游服务可以承受的极限,
那么超过该部分的请求将触发速率限制器来限制电流并阻止它。因此,大量的MQ消费者线程被阻塞,因此代理系统的整体消息消费速度将减慢,最终结果是入口主题堆积。
但是,无论您查看机器的日志还是监视器,由于电流限制造成的阻塞现象都不严重且相对平稳:
其次,如果真的是今天系统入口流量大导致的,所有代理机器(MQ消费者)的积累程度应该差不多。不应该都堆在同一台机器上,而其他499台机器都正常。因此,
检查系统入口流量是否过大。4)MQ数据倾斜?预计500台代理机器应该平等地共享MQ中的消息。有没有可能是数据分发出现了倾斜,导致这台机器分发的消息过多?
其他机器几乎没有消息?检查代理上游系统的代码。系统在向代理发送消息时没有自定义随机播放,因此它将使用MQ的默认selectOneMessageQueue策略。
此策略会将当前消息发送到基于索引% queue_size选择的队列。进一步观察index的逻辑,发现它在初始化时以一个随机数开始,每次访问它时都会增加1:
综合以上两点,效果是:将消息从左到右平均分配到每个队列中,并通过%实现自动循环:
总而言之,MQ的默认shuffle策略是:将消息平均划分到队列中。因此,我们可以排除我们的代理机器因为MQ发送的消息数据倾斜而堆积的可能性。
5)CPU偷跑?提示:CPU占用率表示虚拟机中运行的进程被主机上其他进程/虚拟机占用的CPU时间百分比。高CPU占用率值通常意味着虚拟机中进程的性能下降。
比如机器规格本身是4C,偷换后实际只能用2C。因此,结果是单个请求的RT没有明显变化(不同C之间的差异很小),但C的数量较少。
因此,该机器的整体吞吐量变小,消耗能力变弱,导致堆积。然而,调查发现st是正常的,并且排除了这种可能性:
6)找到线索:MQ消费网站没有变化!绕了一圈没发现什么异常点。因为问题现象是MQ累积,所以我认为可以查看中间件日志来找到线索。果然,通过定向搜索卡住机器的queueId,
发现这个队列的消费站点很久没有推广了,一直卡在某个位置:
提示:MQ拉取消息的机制是,拉取的消息将存储在内存中容量为1000的缓存中,然后内存中的消息将由消费线程消费。当缓存已满时,不会将其从队列中取出。
因此,不确定本地缓存是否总是满的,因为代理消耗停止或消耗极其缓慢,因此MQ将停止将消息拉至队列,因此偏移量没有改变。但是如上所述,
无论从MQ控制台、系统监控指示灯和机器日志来看,这台机器都是正常的,与其他机器没有什么不同。那为什么机器的消费点就是不动呢?
导致堆积越来越严重?7)找到根本原因:某个消费者线程被卡住。提示:对于本地缓存中的消息,MQ将打开多个线程(线程数量由用户指定)来拉取消费。而且为了保证消息不丢失,offset只记录第一条消息。
首先,这个机制是合理的。因为在至少一次语义下,消息允许被多次消费但不允许被错过。假设现在有两个线程同时提取第一条和第二条消息,后一条消息先被执行。
因为前一条消息的执行可能异常,所以不能直接用后一条消息的偏移量更新偏移量,否则消费失败的消息就找不回来了。因此,
消费站点偏移的含义是该位置及其之前的所有消息都已被正确消费(有点类似于Flink的水印机制)。根据上述机制,回到这个问题,
如果该代理机器的任何一个MQ消费线程被阻塞,整个队列的消费站点将始终停留在与阻塞消息对应的偏移量处。此时,尽管其他线程继续正常消耗,
但它不能提前抵消。另一方面,由于上游仍在向队列发送消息,消息只能进入和退出,累积量=最新进入消息的偏移量-消费点偏移量只增不减。
反映在中控台上就是堆积越来越严重了!基于此分析,通过jstack检查所有MQ消费线程的状态,确实发现线程251始终处于可运行状态!
有理由怀疑这是一个卡住的消费者线程。因为在代理系统的业务场景中,大部分耗时都是在RPC同步调用深度学习模型的过程中(快了几百毫秒,也许慢了几秒),
因此,线程大部分时间应该处于等待状态,等待同步调用返回!而这里的251线程总是可运行的,肯定有问题。进一步打印详细信息,找到线程被卡住的具体代码位置:
这里,getImageDetail方法将通过HTTP下载图片,以便深度学习模型可以做出估计。其次,搜索业务日志也发现找不到该线程的日志。因为昨晚10点被困后,
该线程不会生成任何新日志。随着机器日志的滚动清理,所有日志现在都将包含该线程的内容:
至此,代理系统中个别机器出现严重MQ堆积问题的根本原因找到了:该机器的一个消费线程在通过HTTP下载图片时已被卡住,导致整个队列的消费站点无法推进,从而继续堆积。
8)为什么HTTP总是卡住?此时,虽然积累的根本原因已经找到,并且经过尝试,可以在短时间内通过应用程序重启/机器离线的方式暂时解决。但从长远来看,隐患总是存在的,因为近期每隔几天就会不时出现同样的问题。
有必要彻底找出HTTP阻塞的根本原因,以便从根本上解决这一问题。经过几次蹲守,我发现了一些会导致线程卡住的图片URL。我发现不是内部图片地址,地址打不开,也不是jpg结尾的格式:
https://juji . VM health . cn https://978 . VM health . cn https://Xiong . bhjgkjhb . shop但问题是即使你输入了这个无法打开的极端网址,
因为我们为HttpClient设置了5s的超时时间,它最多会卡死5s。为什么好像超时机制没生效,一直卡了十几个小时?提示:HTTP需要在数据传输前建立连接。
这对应于两种超时:1。连接超时,针对建立连接阶段;2.套接字超时,针对数据传输过程中的超时。
经检查,目前代码中只设置了socket timeout,而没有设置connection timeout,因此怀疑上述请求直接卡在了之前的connect阶段。
而且因为没有设置连接超时,请求一直被卡住?但是,在修改代码并尝试再次请求这些地址后,发现仍然会被卡住,需要进一步调查。9)找到HTTP卡住的根本原因提示:找到根本原因。
在特定版本的HttpClient中,基于SSL连接的请求中存在一个bug:实际上,将首先尝试连接,然后设置超时期限,顺序相反。因此,如果您在连接过程中遇到问题,说明超时尚未设置。
这个HTTP请求会一直卡住.
回头看看上面被屏蔽的网址,无一例外都是以https开头的!案子破了。结果发现用于该项目的HttpClient有一个bug。升级HttpClient版本后,再次预发送构造测试请求。
在线程不再被阻塞并全部发送到在线环境后,最近频繁出现的少量机器堆积的问题再也没有出现过。至此,几经周折,问题终于得到彻底解决。4.全面梳理从最外层代理个体机器累积的外观,
我在内部调查中经历了许多关键节点,直到找到根本原因。目前,所有问题都已查明。现在,从上帝的角度来看,由内而外的完整因果链如下:-代理系统将基于HttpClient下载图片。
而且刚好卡死(低概率事件),所以会因为超时不生效而一直卡死;-至少一次基于MQ的机制,
消耗点将始终停留在与阻塞消息对应的偏移量处(尽管其他线程正在正常消耗);-上游系统仍然持续向代理发送消息,因此消息只能进出,并且积累越来越严重;累积量超过某个阈值,
监控警报被触发,并且用户意识到这一点。
第三,这个问题的调查过程略显曲折,但我们也可以学到许多常见的方法和经验教训,本节对此进行了总结:
善用故障排除工具:学会使用jstack、Arthas和jprofile等利器,在不同情况下善用合适的工具,可以有效发现异常并发现线索。
从而逐步找到问题根因;异常的敏感度:有时一些发现问题的线索其实早早就展现在了眼前,但当时因为各种原因(比如最初对问题的疑团很多,未排除的干扰因素多等)导致并不能立马发现线索,
还需多积累经验;广泛查阅资料:除了内网查文档、找相关人员咨询,还要学会去外部英文网站查第一手资料;困难时要坚持:对一些隐蔽的问题,很多时候不是出现一次就能立马发现问题并解决的。
可能需要前前后后经历了几轮排查,最终才能找到根因;补充底层知识:如果最开始能知道MQ 的offset 机制,一些问题就不会走那么多弯路了。后续在用各种中间件的过程中,
要多去了解它们的底层原理;没有玄学问题:代码和机器不会骗人,一切“玄学”问题的背后,都有一套严谨又合理的成因。参考资料
HttpClient Bughttps://issues.apache.org/jira/browse/HTTPCLIENT-1478Connection timeout v.s Socket timeouthttps://stackoverflow.com/questions/7360520/connectiontimeout-versus-sockettimeout作者丨吉多
来源丨公众号:阿里开发者(ID:ali_tech)dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn
关于我们
dbaplus社群是围绕Database、BigData、AIOps的企业级专业社群。资深大咖、技术干货,每天精品原创文章推送,每周线上技术分享,每月线下技术沙龙,
每季度GdevopsDAMS行业大会。
关注公众号【dbaplus社群】,获取更多原创技术文章和精选工具下载
版权声明
1、本文内容转载自一次消息队列堆积问题排查,我把坑踩了个遍!(),或有会员发布,版权归原网站/法人所有。
2、本站仅提供信息发布平台,不承担相关法律责任。
3、文章仅代表作者个人观点,不代表本站立场,未经作者许可,不得转载。
4、若侵犯您的版权或隐私,请联系本站管理员删除。
口碑点评
警告:请理性点评、打分,请文明用语!请给“一次消息队列堆积问题排查,我把坑踩了个遍!”打分并给出您的宝贵点评意见
一次消息队列堆积问题排查,我把坑踩了个遍!收录查询
一次消息队列堆积问题排查,我把坑踩了个遍!SEO综合查询
-
搜索引擎百度PC百度移动头条搜狗360pPC360移动神马
-
权重
-
关键词
-
IP来路
推荐网站
-
微软推出个人版Copilot Pro订阅服务,每月20美元,可以使用Office AI功能
个人版Copilot Pro来了!当地时间周一(1月15日),微软正式发布了Copilot Pro,这意味着和企业一样,个人用户也可以开始使用AI驱动的Office功能了——使用Office软件的AI功能、优先访问最新的OpenAI模型、甚
更新时间:2024-01-26 03:26:28 -
Linux学习第26节,内核发现工作太多时,会让它们排队等待处理
第24节提到,在处理中断时,Linux 内核为了解决“又想做得快,又想做得多”的矛盾,将一次完整的中断处理分为“上半部”和“下半部”两部分,耗时较多但是对实时性要求不高的处理统统放入下半部。2.6.26 版本的 Linux 内核有软中断、
更新时间:2024-01-26 03:26:28 -
第五人格:为何监管者玩家越来越多?网友:享受抓人的快感!
在第五人格手游中,不知小伙伴们是否发现,每当你选择监管者并开始案件还原时,总会出现“您当前选择的阵营队列人数过多”的提示,不得不说,监管者玩家的数量已经变得越来越多,下面小编就来分析一下屠夫玩家变多的原因?一起来看看吧!原因一:享受抓人的快
更新时间:2024-01-26 03:26:28 -
实战总结|记一次消息队列堆积的问题排查
吉多 阿里开发者 2023-07-18 09:01 发表于浙江阿里妹导读本文记录了一次问题的排查过程,从中可以学到不少共性的方法论和经验教训,所以做了提炼归纳。(文末有活动)一、背景本次问题涉及的系统链路如上图,各系统的基本职责为:Prox
更新时间:2024-01-26 03:26:28 -
大数据面试-Kafka 小结
技术是需要自己去沉淀的,沉淀的过程就是在与不断的学习和理解。加油,奥里给Kafka 的相关总结Kafka 架构我们直接看个图:Kafka 压测Kafka 官方自带压力测试脚本(kafka-consumer-perf-test.sh、kafk
更新时间:2024-01-26 03:26:28 -
暗黑破坏神4暗黑4 PS、Xbox主机提示登录列队位置验证中解决办法
暗黑破坏神4是全新大作,好消息是暗黑破坏神4的beta公测抢先试玩和正式开测都按期到来,玩家们可以根据自己的情况试玩或参与公测。部分玩家反馈暗黑破坏神4暗黑4 PS、Xbox主机提示登录列队位置验证中,无法正常进入游戏,为此小编带来暗黑破坏
更新时间:2024-01-26 03:26:28 -
Java项目:并发队列中的任务堆积导致队列溢出
当Java项目中的并发队列中的任务堆积过多时,可能会导致队列溢出,引发一系列问题。下面将详细解释这个问题,并提供一些解决方案。首先,让我们了解一下什么是并发队列。并发队列是在多线程环境下使用的数据结构,它可以安全地处理并发访问和操作。常见的
更新时间:2024-01-26 03:26:28 -
消息队列堆积太多,下游处理不过来怎么办呢?
原文链接:https://mp.weixin.qq.com/s/BhhiUrQECX-KS57rRbrRzQ作为后端程序员日常工作中难免会遇到要跟消息队列打交道的时候,而且在当下微服务的场景下,很多服务的性能不是我们自己能控制的。这不阿粉最
更新时间:2024-01-26 03:26:28 -
数仓/数开面试题真题总结(四)
四.Kafka1.Kafka名词解释和工作方式Producer :消息生产者,就是向kafka broker发消息的客户端。Consumer :消息消费者,向kafka broker取消息的客户端Topic :咱们可以理解为一个队列。Con
更新时间:2024-01-26 03:26:28 -
阴阳师万事屋怎么升级快?阴阳师万事屋快速升级攻略技巧
阴阳师万事屋怎么升级快呢 下面小编为大家带来阴阳师万事屋快速升级攻略,快一起来看看吧。阴阳师万事屋快速升级攻略一句话总结:白天主要卖产品,保持风水玉接近上限,消耗全部火玉;睡觉时主要制作风水产品,火玉自然恢复,只用挂两个委派雷2水2;雷三级
更新时间:2024-01-26 03:26:28