当前位置:首页 > 科技  > 软件

记一次线程池使用不当触发死锁导致RocketMQ消费停滞

来源: 责编: 时间:2024-09-10 09:51:10 218观看
导读背景团队小伙伴突然找到我们团队说,不得了了,线上的RocketMQ又出现了消费停滞,怎么办? 要不要我们先重启一下其实早在之前也出现过一次,当时为了快速恢复业务的,就直接重启解决的。这次因为堆积量不多,所以想对运行环境进行

背景

团队小伙伴突然找到我们团队说,不得了了,线上的RocketMQ又出现了消费停滞,怎么办? 要不要我们先重启一下D7h28资讯网——每日最新资讯28at.com

其实早在之前也出现过一次,当时为了快速恢复业务的,就直接重启解决的。D7h28资讯网——每日最新资讯28at.com

这次因为堆积量不多,所以想对运行环境进行一些环境快照保留。所以就和业务方沟通是否看见接受短暂的消息延时D7h28资讯网——每日最新资讯28at.com

得到肯定答案后就是放手干吧!D7h28资讯网——每日最新资讯28at.com

问题定位

首先我们要确定业务反馈的是否属实,所以需要去RocketMQ dashboard上看看具体的消费进度。D7h28资讯网——每日最新资讯28at.com

图片图片D7h28资讯网——每日最新资讯28at.com

可以看到consumer中并不是全部的queue消费都堆积了,只有一个queuq消息堆积了。D7h28资讯网——每日最新资讯28at.com

这个消费者订阅的topic是分区有序的,正常来说分区有序,如果某个分区的消息单条消息出现了消费异常,必须要等这条消息消费成功(或者是重试结束)后才能继续消费后面的消息。D7h28资讯网——每日最新资讯28at.com

有时候会因为这个原因出现消息堆积是正常的,但是业务对消息重试进行了合理的设置,设置的重试次数比较合理,不会出现长时间的堆积。D7h28资讯网——每日最新资讯28at.com

RocketMQ的消费线程

一般出现这种问题很明显就是线程出现了死锁或者僵死之类的情况。D7h28资讯网——每日最新资讯28at.com

熟悉RocketMQ的都知道RocketMQ消费消息主要是依赖1个线程1个线程池。D7h28资讯网——每日最新资讯28at.com

  1. 以PullMessageService开头的线程, 主要用来拉去消息

图片图片D7h28资讯网——每日最新资讯28at.com

  1. 以ConsumeMessageThread开头的线程(实际是一个线程池),主要用来执行消费逻辑。

图片图片D7h28资讯网——每日最新资讯28at.com

直到了RocketMQ的消费线程模型后我们就好解决了。我们直接通过jstack命令查看线程的堆栈信息。D7h28资讯网——每日最新资讯28at.com

线程快照分析

我们直接通过jstack命令生成线程快照。D7h28资讯网——每日最新资讯28at.com

jstack <pid> > thread_dump_$(date +%Y%m%d_%H%M%S).txt


D7h28资讯网——每日最新资讯28at.com

pid 和后面的 thread_dump_$(date +%Y%m%d_%H%M%S).txt自己随便取个名字就行。自己记得就行。D7h28资讯网——每日最新资讯28at.com

由于应用运行在pod中,生成了我们就下载到本地。D7h28资讯网——每日最新资讯28at.com

我们自己看还是比较难分析出分体。这里我们直接使用一个在线的网站进行线程快照的分析。D7h28资讯网——每日最新资讯28at.com

fastthread

fastthread是一个在线的线程快照分析工具,可以直接将线程快照上传到这个网站进行分析。D7h28资讯网——每日最新资讯28at.com

图片图片D7h28资讯网——每日最新资讯28at.com

我们上传我们下载的线程快照文件。D7h28资讯网——每日最新资讯28at.com

然后进行线程分析:D7h28资讯网——每日最新资讯28at.com

图片图片D7h28资讯网——每日最新资讯28at.com

很快定位到阻塞其他线程的代码。D7h28资讯网——每日最新资讯28at.com

这里的代码被我打码了。D7h28资讯网——每日最新资讯28at.com

arhtas

如果我们使用arthas也可以很方便的找到阻塞的线程。D7h28资讯网——每日最新资讯28at.com

thread -b

arthas 提供了thread -b, 一键找出那个罪魁祸首。D7h28资讯网——每日最新资讯28at.com

问题元凶找到

通过阻塞代码我们很快定位到是由于线程池使用不当导致的阻塞。D7h28资讯网——每日最新资讯28at.com

线程池使用不当

什么情况下会出现线程池使用不当导致的"死锁"呢?D7h28资讯网——每日最新资讯28at.com

我们看看下面的demo:D7h28资讯网——每日最新资讯28at.com

public class XiaoZouExample {    public static void main(String[] args) {        ExecutorService executor = new ThreadPoolExecutor(2, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());        // 提交两个外部任务        for (int i = 0; i < 2; i++) {            executor.submit(new OuterTask(executor));        }        // 等待一段时间后关闭线程池        try {            Thread.sleep(10000);        } catch (InterruptedException e) {            e.printStackTrace();        }        executor.shutdown();    }    static class OuterTask implements Runnable {        private final ExecutorService executor;        public OuterTask(ExecutorService executor) {            this.executor = executor;        }        @Override        public void run() {            System.out.println("小奏技术 Outer task started by thread: " + Thread.currentThread().getName());            // 创建一个Future来等待内部任务的结果            Future<?> future = executor.submit(new InnerTask());            try {                // 等待内部任务完成                future.get();            } catch (InterruptedException | ExecutionException e) {                e.printStackTrace();            }            System.out.println("小奏技术 Outer task finished by thread: " + Thread.currentThread().getName());        }    }    static class InnerTask implements Runnable {        @Override        public void run() {            System.out.println("小奏技术 Inner task started by thread: " + Thread.currentThread().getName());            try {                // 模拟长时间运行的任务                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("小奏技术 Inner task finished by thread: " + Thread.currentThread().getName());        }    }}
  • 运行结果

图片图片D7h28资讯网——每日最新资讯28at.com

可以看到没有任何任务执行完成,线程池一直处于被阻塞状态。D7h28资讯网——每日最新资讯28at.com

核心原因就是首先线程池的核心线程数是2,核心线程用来执行2个任务,用完了所有线程。D7h28资讯网——每日最新资讯28at.com

然后在核心线程执行的2个任务中又用原来的线程池进行执行任务,这时候因为没有线程可以去执行任务了,所以会添加到阻塞队列中等待核心线程执行完任务后再执行。D7h28资讯网——每日最新资讯28at.com

但是核心线程想要释放任务又必须等待这两个子任务执行完,这样就形成了一个死锁。D7h28资讯网——每日最新资讯28at.com

解决方案

解决方式有多种,最简单的方式可以考虑不要使用队列,直接使用SynchronousQueue。D7h28资讯网——每日最新资讯28at.com

ExecutorService executor = new ThreadPoolExecutor(2, 5, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>());

让多的任务直接通过主线程执行或者丢弃任务。D7h28资讯网——每日最新资讯28at.com

当然最好的方式就是避免这种情况的发生,合理的使用线程池,不要线程池中的任务还要使用这个线程池去执行任务。D7h28资讯网——每日最新资讯28at.com

这种情况是比较难避免的,因为现在大部分业务开发都是隐式使用线程池,自己也不知道自己用的哪个线程池。D7h28资讯网——每日最新资讯28at.com

比如spring的@Async注解,@Scheduled注解等等。D7h28资讯网——每日最新资讯28at.com

总结

线程池的使用还是要尽量消息,要避免出现线程池中的任务继续使用该线程池去执行任务,出现死锁。D7h28资讯网——每日最新资讯28at.com

也可以考虑对线程池进行监控,避免出现大量任务阻塞。D7h28资讯网——每日最新资讯28at.com

这个问题想要复现需要大量任务并且超过核心线程数才能复现,还是比较难复现的,只有线上大流量的时候才能复现。D7h28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-112791-0.html记一次线程池使用不当触发死锁导致RocketMQ消费停滞

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 深入理解 Babel - 微内核架构与 ECMAScript 标准化

下一篇: 我尝试重现 React 的 useState() Hook 并失去了工作机会

标签:
  • 热门焦点
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • 学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 三分钟白话RocketMQ系列—— 如何发送消息

    我们知道RocketMQ主要分为消息 生产、存储(消息堆积)、消费 三大块领域。那接下来,我们白话一下,RocketMQ是如何发送消息的,揭秘消息生产全过程。注意,如果白话中不小心提到相关代
  • 每天一道面试题-CPU伪共享

    前言:了不起:又到了每天一到面试题的时候了!学弟,最近学习的怎么样啊 了不起学弟:最近学习的还不错,每天都在学习,每天都在进步! 了不起:那你最近学习的什么呢? 了不起学弟:最近在学习C
  • 微博大门常打开,迎接海外画师漂洋东渡

    作者:互联网那些事&ldquo;起猛了,我能看得懂日语了&rdquo;。&ldquo;为什么日本人说话我能听懂?&rdquo;&ldquo;中文不像中文,日语不像日语,但是我竟然看懂了&rdquo;&hellip;&hell
  • iQOO Neo8 Pro抢先上架:首发天玑9200+ 安卓性能之王

    经过了一段时间的密集爆料,昨日iQOO官方如期对外宣布:将于5月23日推出全新的iQOO Neo8系列新品,官方称这是一款拥有旗舰级性能调校的作品。随着发布时
  • 苹果140W USB-C充电器:采用氮化镓技术

    据10 月 30 日 9to5 Mac 消息报道,当苹果推出新的 MacBook Pro 2021 时,该公司还推出了新的 140W USB-C 充电器,附赠在 MacBook Pro 16 英寸机型的盒子里,也支
  • 由于成本持续增加,笔记本产品价格预计将明显上涨

    根据知情人士透露,由于材料、物流等成本持续增加,笔记本产品价格预计将在2021年下半年有明显上涨。进入6月下旬以来,全球半导体芯片缺货情况加剧,显卡、处理器
  • 外交部:美方应停止在网络安全问题上不负责任地指责他国

      中国外交部今天(16日)举行例行记者会。会上,有记者问,美国情报官员称,他们正在阻拦来自中国以及其他国家的黑客获取相关科研成果。 中方对此有何评论?对此
Top