结合源码聊一聊为何线上RocketMQ偶尔出现system busy

news2025/4/24 4:30:55

这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党

RocketMQ 版本

  • 5.1.0

背景

继之前研究过的RocketMQ发送消息还有这种坑?遇到SYSTEM_BUSY不重试?

今天我们来分析分析RocketMQ什么情况下会出现system busy,因为线上的RocketMQ集群偶尔会出现[PCBUSY_CLEAN_QUEUE]broker busy, start flow control for a while。所以打算详细研究下为何会出现这种情况

总共有几种system busy

我们通过查看SYSTEM_BUSY状态码调用的方式可以看到总共有如下几种system busy

  1. [REJECTREQUEST]system busy, start flow control for a while
  2. too many requests and system thread pool busy, RejectedExecutionException
  3. [TIMEOUT_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue
  4. [PCBUSY_CLEAN_QUEUE]broker busy, start flow control for a while, period in queue: %sms, size of queue: %d

Grpc这边的异常我们暂时不讨论,因为只是简单的超时判断,和其他四种不太一样

下面我们结合源码来详细分析这四种情况是如何出现的

[REJECTREQUEST]system busy

何时会抛出[REJECTREQUEST]system busy

先说结论

  1. 操作系统页面缓存(Os PageCache)繁忙
  2. 如果开启堆外内存存储消息,堆外内存不够也会抛出[REJECTREQUEST]system busy

下面我们来结合源码具体分析下

我们直接全局搜索找到对应的源码,然后看看方法

这里看不到实际的逻辑,所以我们继续往上看看,NettyRequestProcessor接口的实现类有很多,我们主要看SendMessageProcessor

这里第一个if else我们不用管,我们现在不是使用的这种模式部署的,主要看下面的代码

这里可以看到是否抛出[REJECTREQUEST]system busy异常主要有两个条件

  1. 检查操作系统页面缓存(Os PageCache)是否繁忙
  2. 检查暂存器池(transientStorePool)是否不足

如何检查操作系统页面缓存(Os PageCache)是否繁忙

@Override
    public boolean isOSPageCacheBusy() {
        long begin = this.getCommitLog().getBeginTimeInLock();
        long diff = this.systemClock.now() - begin;

        return diff < 10000000
            && diff > this.messageStoreConfig.getOsPageCacheBusyTimeOutMills();
    }
  • begin: (将消息写入Commitlog文件所持有锁的时间),beginbeginTimeInLock,在asyncPutMessages中赋值

也就是消息追加到MappedFile的开始时间

  • diff: (一次消息追加过程中持有锁的总时长,即往内存映射文件或pageCache追加一条消息所耗时间)

diff 大于 配置的osPageCacheBusyTimeOutMills时间,默认1s就表示Os PageCache Busy

如何检查暂存器池(transientStorePool)是否不足

这里的transientStorePool实际是对外内存,判断条件的代码我们来看看

    @Override
    public boolean isTransientStorePoolDeficient() {
        return remainTransientStoreBufferNumbs() == 0;
    }
    public int remainTransientStoreBufferNumbs() {
        return this.transientStorePool.availableBufferNums();
    }
    public int availableBufferNums() {
        if (messageStore.isTransientStorePoolEnable()) {
            return availableBuffers.size();
        }
        return Integer.MAX_VALUE;
    }

首先判断是否开启transientStorePoolEnable堆外内存存储消息,默认为false

如果没开启返回Integer.MAX_VALUE一定不为0.

所以如果没有开启transientStorePoolEnable,则只会判断操作系统页面缓存(Os PageCache)是否繁忙

开启了transientStorePoolEnable还会判断堆外内存是否够用

堆外内存的相关配置通过transientStorePoolSizemappedFileSizeCommitLog配置,默认为5个ByteBuffer,每个1G
所以开启堆外内存存储消息,会额外消耗5G内存。

如果对外内存不够则建议调整transientStorePoolSize的值

too many requests and system thread pool busy

这里结合源码分析主要是在线程池提交任务被拒绝的时候会给client返回这个异常,我们具体来看看这个线程池

我们看看队列的容量是多少

this.sendThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getSendThreadPoolQueueCapacity());

可以看到默认是1w,也就是如果发送消息的请求超过了1w未处理,就会直接给client抛出这个异常

[TIMEOUT_CLEAN_QUEUE]broker busy

我们全局搜索[TIMEOUT_CLEAN_QUEUE]broker busy

有两处地方,我们先看看RemotingProtocolServer

this.timerExecutor.scheduleAtFixedRate(this::cleanExpireRequest, 10, 10, TimeUnit.SECONDS);

可以看到使用启动器启动扫描去处理过期的请求,如何处理呢

这里就是检验线程池中的任务是否超过执行时间,如果超过则移除,然后给client返回[TIMEOUT_CLEAN_QUEUE]broker busy,具体的超时时间不同的线程池有不同的配置,

消息发送的3s

我们再看看BrokerFastFailure

这里其实可以看到也是清理线程池的BlockingQueue,和上面的RemotingProtocolServer类似,不同的是这里的这些BlockingQueue主要是给broker使用的,上面的主要是给远程通信用的。

[PCBUSY_CLEAN_QUEUE]broker busy

这里可以看到主要是如果发生了 OS page cache is busy,每隔10毫秒执行一次,直接去将broker中等待处理的消息queue全部丢弃,返回失败

这里和上面[TIMEOUT_CLEAN_QUEUE]broker busy不同的是如果发生OS page cache is busy是直接丢弃,不是等待超时

两者都需要broker开启快速失败即brokerFastFailureEnable为true,默认为true

总结

本次我们结合源码分析了出现system busy的四种情况

  1. OS page cache is busy
  2. broker中消息发送线程池(sendMessageExecutor)处理任务超时
  3. OS page cache is busy,开始清理送线程池(sendMessageExecutor)中的queue任务
  4. 消息发送线程池(sendMessageExecutor)队列容量满了(默认1w)

如何缓解这几种异常呢?本质都是broker的压力太大了,处理不过来。

最好的解决方式就是提升broker的处理速度,即RocketMQ的 QPS。
有以下几种方式

  1. 开启读写分离(即transientStorePoolEnable = true)
  2. 扩容broker集群
  3. 优化broker qps(实际1中的方法也属于这条)

不太可取方案:

  1. 关闭快速失败(brokerFastFailureEnable = true)
  2. 扩大sendMessageExecutor线程池的队列容量
  3. 增大osPageCacheBusyTimeOutMills超时时间

参考

  • 博客
  • RocketMQ源码

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

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

相关文章

从概念到现实:ChatGPT 和 Midjourney 的设计之旅

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 在现代技术的世界中&…

媒体基础:打开多模态大模型的新思路

编者按&#xff1a;2023年是微软亚洲研究院建院25周年。25年来&#xff0c;微软亚洲研究院探索并实践了一种独特且有效的企业研究院的新模式&#xff0c;并以此为基础产出了诸多对微软公司和全球社会都有积极影响的创新成果。一直以来&#xff0c;微软亚洲研究院致力于创造具有…

【Js】数据处理

一、对象 1&#xff09;、Object. hasOwnProperty&#xff08;&#xff09; hasOwnProperty() 方法会返回一个布尔值&#xff0c;指示对象自身属性中&#xff08;非继承属性&#xff09;是否具有指定的属性&#xff0c; 如果 object 具有带指定名称的属性&#xff0c;则 hasOwn…

AT2401C 功率放大器(PA)射频前端集成芯片

AT2401C 功率放大器&#xff08;PA&#xff09;射频前端集成芯片&#xff0c;它是一款面向Zigbee&#xff0c;无线传感网络以及其他2.4GHz 频段无线系统的全集成射频功能的射频前端单芯片。AT2401C 内部集成了功率放大器(PA)&#xff0c;低噪声放大器(LNA)&#xff0c;芯片收发…

学习小程序开发一:基本的组件学习使用

文章目录 01-小程序的宿主环境-组件一、小程序中组件的分类二、常用的视图容器类组件三、view组件的基本使用1、list.wxml代码实现2、list.wxss代码实现 四、scroll-view组件的基本使用实现步骤&#xff1a;1、list.wxml代码实现2、list.wxss代码实现 五、swiper 和 swiper-ite…

软件外包开发流程

软件外包是将软件开发任务委托给外部供应商或团队的一种常见做法。以下是软件外包的一般流程以及需要注意的问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 软件外包流程&#xff1a; 确定需求&…

基于JavaWeb的图书售卖网站(源码+部署+LW)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于JavaWeb的图书售卖网…

1688拍立淘接口,按图搜索1688商品接口,图片搜索商品接口,1688API接口

按图搜索1688商品的方法如下&#xff1a; 打开1688平台&#xff0c;点击首页右上角的搜索框&#xff0c;进入搜索页面。 点击搜索框右侧的相机图标&#xff0c;选择“拍照”或“相册”&#xff0c;上传你想要搜索的图片。 等待图片上传完成&#xff0c;系统会自动识别图片中的…

一文读懂flutter线程: 深入了解Flutter中的多线程编程

深入了解Flutter中的多线程编程 前言一、为什么需要多线程&#xff1f;二、在Flutter中创建线程三、多线程的最佳实践四、Flutter中的多线程示例五、Flutter中的多线程错误处理六、Flutter中的多线程性能优化七、安全性和隐私考虑八、跨平台性考虑 总结 前言 在移动应用开发领域…

高校教务系统登录页面JS分析——安徽工程大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

五.镜头知识之镜片组成 与 六.镜头知识之滤光片与IRCUT

五.镜头知识之镜片组成 文章目录 五.镜头知识之镜片组成5.1 线激光模组镜头手册5.2 镜片组成5.3 **正透镜&#xff08;Positive Lens&#xff09;**和**负透镜&#xff08;Negative Lens&#xff09;**5.3.1 **近视镜是凸透镜还是凹透镜&#xff1f;** 六.镜头知识之滤光片与IR…

多模态大模型:ChatGPT迎来重磅升级,开启看图、听声音的新时代

近日&#xff0c;OpenAI宣布对ChatGPT进行了重磅升级&#xff0c;实现了看图、听声音和输出语音内容的功能。这一突破标志着通用人工智能&#xff08;AGI&#xff09;的重要里程碑&#xff0c;为未来的发展开启了全新的时代。OpenAI计划在未来两周向Plus和企业版用户提供这些功…

思科拟推出PuzzleFS驱动,采用Rust语言开发

据了解&#xff0c;PuzzleFS宣称是“下一代 Linux 容器文件系统”&#xff0c;并使用Rust语言编写&#xff0c;具有“快速镜像构建”、“直接挂载支持”、“内存安全保证”等功能mroeoyw。 Multiable万达宝制造ERP(www.multiable.com.cn/solutions_zz)支持自定义栏位,并智能制…

【Unity】VR开发基础1-工具准备-下载Unity

用VR开发&#xff0c;首选Unity。 所以我们先从下载Unity开始。 前往unity.com/download&#xff0c;大家的系统基本都是Windows&#xff0c;我也是&#xff0c;所以下载Windows版本。 安装完成后打开UnityHub&#xff0c;点击安装选项卡&#xff0c;点击安装编辑器。 选择…

海外媒体发稿:10大海外媒体推广秘诀助力你的全球业务飞跃-华媒舍

随着全球化的深入&#xff0c;越来越多的企业开始将目光投向海外市场。而对于海外市场的开拓&#xff0c;海外媒体推广成为一个不可或缺的重要手段。本文将为大家介绍10大海外媒体推广秘诀&#xff0c;助力你的全球业务飞跃。 1. 确定目标受众 要明确你的目标受众是谁。不同的…

mysql数据库为什么要使用连接池?

连接池是MySQL数据库访问的关键组件&#xff0c;它负责管理和维护一组数据库连接&#xff0c;允许应用程序高效地重用这些连接&#xff0c;从而降低了连接的建立和断开开销&#xff0c;提高了性能、资源利用率和可伸缩性。 &#xff08;一&#xff09;为什么要用连接池&#x…

pytorch学习第二篇:张量

tensor与numpy import torch import numpy as npnumpy数组 到 张量tensor n np.ones(5) t torch.from_numpy(n)NumPy 数组中的变化反映在张量中 np.add(n, 1, outn) print(f"t: {t}") print(f"n: {n}")张量到 NumPy 数 t torch.ones(5) print(f&quo…

[ spring boot入门 ] java: 错误: 无效的源发行版:17

因为我目前idea中使用的是jdK8&#xff0c;而在pom.xml文件里是17&#xff0c;所以我需要将所有地方修改为jdk8 pom.xml的jdk版本为8 maven的setting.xml文件 jdk为8 还有Java Compiler 还有Project Structure 里面的project 和 module

2023北京市人工智能大模型场景融合与产业发展专场活动盛大召开

2023年10月12日&#xff0c;“2023北京市人工智能大模型场景融合与产业发展专场”活动在中关村软件园国际会议中心盛大召开&#xff0c;本次活动作为助力北京民营企业创新领跑行动计划的专场活动&#xff0c;由北京市委网信办、北京市科委、中关村管委会、北京市经信局、北京市…

2023年中国水生植物产业链、产值及市场规模分析[图]

水生植物是生态学范畴上的类群&#xff0c;是不同分类群植物通过长期适应水环境而形成的趋同性生态适应类型。水生植物应用范围广&#xff0c;既可以作为蔬菜食用&#xff0c;又可以作为园林观赏植物以及饲料作物等。水生蔬菜是中国蔬菜生产中的一大特色,其品种之多&#xff0c…