RabbitMQ(六)流量控制 -- basic.qos,prefetch_count

面试大杀器:消息中间件如何实现消费吞吐量的百倍优化? 目录 (1)前请提示 (2)unack消息的积压问题 (3)如何解决unack消息的积压问题 (4)高并发场景下的内存溢出问题 (5)低吞吐量问题 (6)合理设置prefetch count (7)阶段性总结 1、前情提示 这篇文章,我们将会对ack底层的delivery tag机制进行更加深入的分析,让大家理解的更加透彻一些。 面试时,如果被问到消息中间件数据不丢失问题的时候... 阅读详情

原文地址:http://my.oschina.net/hncscwc/blog/195560


消费者在开启acknowledge的情况下,对接收到的消息可以根据业务的需要异步对消息进行确认。

然而在实际使用过程中,由于消费者自身处理能力有限,从rabbitmq获取一定数量的消息后,希望rabbitmq不再将队列中的消息推送过来,当对消息处理完后(即对消息进行了ack,并且有能力处理更多的消息)再接收来自队列的消息。在这种场景下,我们可以通过设置basic.qos信令中的prefetch_count来达到这种效果。

先直观的看看设置了prefetch_count的效果,:

1) 对比测试:两个消费者都订阅同一队列,no_ack均设置为false即开启acknowledge机制,且均未设置prefetch_count,向队列发布5条消息

结果:不管消息是否被ack,rabbitmq会轮流向两个消费者投递消息,第一个消费者收到"1","3","5"三条消息, 第二个消费者收到"2","4"两条消息。

2)prefetch_count设置测试:两个消费者都订阅同一队列,开启acknowledge机制,第一个消费者prefetch_count设置为1,另一个消费者未设置prefetch_count,同样向队列发布5条消息

结果:rabbitmq向第一个消费者投递了一条消息后,消费者未对该消息进行ack,rabbitmq不会再向该消费者投递消息,剩下的四条消息均投递给了第二个消费者

看完效果后,再来看看rabbitmq里的一些实现。

1. rabbitmq对basic.qos信令的处理

首先,basic.qos是针对channel进行设置的,也就是说只有在channel建立之后才能发送basic.qos信令。

在rabbitmq的实现中,每个channel都对应会有一个rabbit_limiter进程,当收到basic.qos信令后,在rabbit_limiter进程中记录信令中prefetch_count的值,同时记录的还有该channel未ack的消息个数。

注:其实basic.qos里还有另外两个参数可进行设置,prefetch_size和global,但是RabbitMQ没有实现prefetch_size,并在3.3.0版本中对global这个参数的含义进行了重新定义,即glotal=true时表示在当前channel上所有的consumer都生效,否则只对设置了之后新建的consumer生效

global Meaning of prefetch_count in AMQP 0-9-1 Meaning of prefetch_count in RabbitMQ
false shared across all consumers on the channel applied separately to each new consumer on the channel
true shared across all consumers on the connection shared across all consumers on the channel


一个 queue 中消息最大保存量可以在声明 queue 的时候通过设置 x-max-length 参数为非负整数进行指定。Queue 长度的选取需要考量 就绪消息量、被忽略的未确认消息量,以及消息大小。当 queue 中的消息量达到了设定的上限时,为了给新消息腾出空间,将会从该 queue 用于保存消息的队列的前端将“老”消息丢弃或者 dead-lettered 。

下面的 Java 示例展示了如何声明一个最多保存 10 条消息的 queue :

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-max-length", 10);
channel.queueDeclare("myqueue", false, false, false, args);

2. 队列中的消息投递给消费者时的处理

当rabbitmq要将队列中的一条消息投递给消费者时,会遍历该队列上的消费者列表,选一个合适的消费者,然后将消息投递出去。其中挑选消费者的一个依据就是看消费者对应的channel上未ack的消息数是否达到设置的prefetch_count个数,如果未ack的消息数达到了prefetch_count的个数,则不符合要求。当挑选到合适的消费者后,中断后续的遍历。

01 rabbit_amqqueue_process.erl
02  
03 deliver_msgs_to_consumers(_DeliverFun, true, State) ->
04     {true, State};
05 deliver_msgs_to_consumers(DeliverFun, false,
06                           State = #q{active_consumers =
07                                      ActiveConsumers}) ->
08     case priority_queue:out_p(ActiveConsumers) of
09         {empty, _} ->
10             {false, State};
11         {{value, QEntry, Priority}, Tail} ->
12             {Stop, State1} =
13                 deliver_msg_to_consumer(DeliverFun, QEntry,
14                                         Priority,
15                                         State#q{active_consumers =
16                                                 Tail}),
17             %%如果处理结果为false,遍历下一个消费者
18             deliver_msgs_to_consumers(DeliverFun, Stop, State1)
19     end.
20  
21 deliver_msg_to_consumer(DeliverFun, E = {ChPid, Consumer},
22                         Priority, State) ->
23     ...
24     %%判断是否可以将消息投递给该消费者
25     case rabbit_limiter:can_send(C#cr.limiter,
26                                  Consumer#consumer.ack_required,
27                                  Consumer#consumer.tag) of
28         %%可以投递,再将该消费者放到队列的尾部
29         {continue, Limiter} ->
30             AC1 = priority_queue:in(E, Priority,
31                                     State#q.active_consumers),
32             %%将消息投递给消费者
33             deliver_msg_to_consumer0(DeliverFun, Consumer,
34                                      C#cr{limiter = Limiter},
35                                      State#q{active_consumers = AC1})
36     ...
37  
38 rabbit_limiter.erl
39  
40 handle_call({can_send, QPid, AckRequired}, _From,
41             State = #lim{volume = Volume}) ->
42     case prefetch_limit_reached(State) of
43         %%未ack的消息数达到prefetch_count设置的个数
44         true  -> {reply, false, limit_queue(QPid, State)};
45         false -> {reply, true,
46                   %%消息需要被ACK, volume加1
47                   State#lim{volume = if AckRequired -> Volume + 1;
48                                         true        -> Volume
49                                      end}}
50     end
51  
52 prefetch_limit_reached(#lim{prefetch_count = Limit,
53                             volume = Volume}) ->
54     Limit =/= 0 andalso Volume >= Limit.



3. 消费者对消息ack后的处理

当消费者对消息进行ack后,最终会修改该消费者对应channel中未ack的消息数,这样队列又可以将消息投递给该消费者。

1 rabbit_limiter.erl
2  
3 handle_cast({ack, Count}, State = #lim{volume = Volume}) ->
4     NewVolume = if Volume == 0 -> 0;
5                    true        -> Volume - Count
6                 end,
7     {noreply, maybe_notify(State, State#lim{volume = NewVolume})};



4. 注意

prefetch_count在no_ask=false的情况下生效,即在自动应答的情况下这两个值是不生效的

C客户端里,用amqp_basic_qos函数来设置


参考:

http://www.rabbitmq.com/consumer-prefetch.html



RabbitMQ报错consumer prefetch count is not set for ‘queue ‘Queue name‘ in vhost ‘vhost name‘‘ 于是就迈上了漫长的百度,bing,google,ChatGPT,优快云之旅,无奈全都没用。报错的核心内容是 consumer prefetch count is not set for 'queue 'TWarning' in vhost 'tutu'',大概意思是没有设置 prefetch count,我一看代码,不对啊,我设置过了的啊,就在代码第二行(也有可能是让我在服务器段设置,但新手小白的我是真的不会设置啊!于是删除virtual host,重新设置,问题解决!不出意外的话是要出意外了,果然。 阅读详情

相关推荐

消息队列之KAFKA

kafka

の博客 168

RabbitMQ的并发参数(concurrency和prefetch)

版本信息: JDK:8 SpringBoot 2.1.3.RELEASE RabbitMQ消费端配置: spring: rabbitmq: host: localhost port: 5672 username: guest password: guest listener: simple: # acknowledge-mode: manual # 手动确定(默认自动确认) concurrency: 1 # 消费.

海子@幸福人 2万+

rabbitmq的接口函数说明,api参数使用说明

rabbitmq的提供的各个接口函数使用说明,函数有 1、amqp_new_connection(声明一个新的connection) 2、amqp_open_socket(获取socket) 3、amqp_set_sockfd(将connection和sockfd进行绑定) 4、amqp_login(用于登录RabbitMQ server,主要目的为了进行权限管理) 5、amqp_channel_open(用于关联conn和channel) 6、amqp_exchange_declare(声明exchange) 7、amqp_queue_declare(声明queue) 8、amqp_queue_bind(声明binding,已经有的绑定直接返回,没有绑定的就会绑定) 9、amqp_basic_qos(控制预取消息数) 10、amqp_basic_consume(指定要接收的队列) 11、amqp_consume_message(接收数据) 12、int amqp_basic_ack(发送ask确认) 13、amqp_basic_reject(拒绝ask) 14、amqp_basic_publish(发布消息) 15、amqp_simple_wait_frame(回调等待服务器的结果返回) 16、amqp_basic_get(客户端主动获取服务器的下一条消息) 17、关闭 18、AE交换机的使用 19、死信交换机的使用

RabbitMQ并发消费者关键参数prefetch,concurrency

线上项目发生一次消息堆积问题,项目中使用的是rabbitmq,所以对rabbitmq的消息堆积问题进行了深入的了解,学习. 消息堆积的主要原因有以下几种: (1)消费者的速度大大慢于生产者的速度,速度不匹配引起的堆积 (2)消费者实例IO严重阻塞或者消费者所在服务器宕机 (3)消费者业务处理异常导致的消息堆积 项目中大部分使用@RabbitmqListener注解的方式处理业务代码中MQ的消费,这个注解用于监听指定的队列,如果containerFactory未指定,默认使用SimpleRabbitListe

u014439693的博客 2万+

Plant Simulation 实战指南:从二次分配问题到优化布局设计

本文是一份Plant Simulation实战指南,详细讲解了如何利用该仿真软件解决工厂布局中的二次分配问题。通过从数据准备、模型搭建到集成遗传算法进行自动化优化的完整流程,帮助工程师在数字孪生环境中高效寻找最优设备布局方案,从而显著降低物流成本,提升生产效率。

i1j2k的博客 564

别再只玩积木了!用乐高EV3和官方软件,手把手教你做个能巡线的小车(附完整代码)

本文详细介绍了如何利用乐高EV3套件和官方软件制作智能巡线机器人,从硬件组装到软件编程全面覆盖。通过传感器原理讲解、控制算法调试等工程化细节,帮助读者掌握机器人开发的核心理念,特别适合STEAM教育和硬件编程爱好者实践。

weixin_30776273的博客 449

rabbitmq——prefetch count

消费者在开启acknowledge的情况下,对接收到的消息可以根据业务的需要异步对消息进行确认。 然而在实际使用过程中,由于消费者自身处理能力有限,从rabbitmq获取一定数量的消息后,希望rabbitmq不再将队列中的消息推送过来,当对消息处理完后(即对消息进行了ack,并且有能力处理更多的消息)再接收来自队列的消息。在这种场景下,我们可以通过设置basic.qos信令中的prefetc

每天积累一点,一年后你会发现,自己变化很大 2万+

本地部署AI应用:基于Google Gemini的banana-prompt快速上手指南

AI应用开发的核心在于将大模型能力集成到实际场景中,其原理是通过API调用将用户输入转化为模型可理解的指令,再由模型生成响应。这一技术价值在于降低AI应用开发门槛,实现数据本地化处理与隐私保护。在工程实践中,开发者常面临环境配置复杂、API集成繁琐等挑战。本文聚焦于使用banana-prompt工具包,通过TypeScript技术栈和npm包管理,快速在Windows本地部署基于Google Gemini API的AI应用。该方案特别适用于ai-prompts提示词工程和content-creation内容

weixin_27188815的博客 314

rabbitmq--prefetch count

消费者在开启acknowledge的情况下,对接收到的消息可以根据业务的需要异步对消息进行确认。 然而在实际使用过程中,由于消费者自身处理能力有限,从rabbitmq获取一定数量的消息后,希望rabbitmq不再将队列中的消息推送过来,当对消息处理完后(即对消息进行了ack,并且有能力处理更多的消息)再接收来自队列的消息。在这种场景下,我们可以通过设置basic.qos信令中的prefetch_

hncscwc的博客 6550

Claude Code 任务编排 头脑风暴与 疯狂拷问:Superpowers vs Grill-me 硬核对比与工程落地

Superpowers和Grill-me是AI编程中的互补工具:Superpowers提供工程化开发流程(从需求梳理到代码审查),确保规范执行;Grill-me通过持续追问帮助厘清需求,避免方向偏差。两者结合形成"构思-拷问-执行"工作流,前者负责方案生成与落地,后者专注需求审查。根据场景选择:个人项目可用Grill-me快速澄清需求,企业项目推荐Superpowers全流程,复杂开发则建议组合使用。它们分别解决"如何落地"和"是否对齐"的问题,共

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 324

【Word提效 No.010】使用AI一键复制格式刷应用格式

本文介绍利用AI工具WorkBuddy实现Word文档格式批量复制的自动化解决方案。通过简单指令即可将指定段落的格式一键应用到多个目标段落,解决传统格式刷操作繁琐、易出错的问题。方案包含三步操作:准备文档、输入指令模板、验收效果,并提供多种场景的现成指令示例。该工具支持字体、段落等格式属性的批量复制,且不会覆盖原文件,适用于论文、手册等文档的格式统一需求。

u011186532的专栏 77

RabbitMQ(四)、流量控制

RabbitMQ流量控制服务端流量控制1. 队列容量设置2. 内存控制 vm_memory_high_watermark3. 磁盘控制消费端流量控制 服务端流量控制 1. 队列容量设置 x-max-length:最大长度 x-max-length-bytes:队列最大容量 2. 内存控制 vm_memory_high_watermark RabbitMQ 会在启动和执行命令 rabbitmqctl set_vm_memory_high_watermark 40%(百分比) 的时候检测系统所安装的内存总量。默

雨后是冰雹 1172

地下管网巡检机器人:基于YOLOv8与UI界面的智能化系统设计与实现

通过YOLOv8模型的目标检测功能结合实时视频流,我们能够实现对地下管网巡检机器人的智能化控制。系统通过图像识别技术帮助巡检人员快速识别管道中的各种缺陷和障碍物,从而提高巡检效率和准确性。未来,我们可以继续优化模型,增加更多的目标类别,并通过强化学习等方法提高机器人的自主巡检能力。此外,随着硬件技术的发展,未来的巡检机器人可能会具备更强的感知能力和更高的智能水平。

YOLO 529

BunnyPHP预取计数(QoS)优化:如何实现高效的消息流控制

在当今的高并发应用场景中,消息队列已成为系统架构的核心组件,而**BunnyPHP预取计数(QoS)优化**正是实现高效消息流控制的关键技术。作为一款纯PHP实现的AMQP客户端库,BunnyPHP通过其强大的QoS机制,帮助开发者精细控制消息消费流程,确保系统稳定性和资源利用率达到最佳状态。 ## 🚀 什么是BunnyPHP QoS预取计数? **QoS(Quality of Servic

gitblog_01196的博客 333

uniapp:实现APP获取陀螺仪数据、加速传感器、线性加速传感器,uniApp实时监听陀螺仪【XYZ】数据及停止监听与资源释放等功能示例源码,根据需求做功能(完美兼容Android安卓、苹果ios)

uniapp陀螺仪,uniapp加速传感器,uniapp线性加速传感器,APP陀螺仪数据,uniapp app 端获取陀螺仪数据示例代码,手机中获取陀螺仪的数据,uniApp实时获取陀螺仪xyz数据,android陀螺仪方向,获得陀螺仪传感器,处理传感器数据,停止监听与资源释放,Android使用陀螺仪,uniapp苹果ios陀螺仪,uni-app设备之(加速计,罗盘,陀螺仪)插件安卓/IOS APP提供了获取陀螺仪数据的能力,手机陀螺仪传感器获得手机自身旋转的角度,陀螺仪获取旋转角度,陀螺仪、加速度传感器

✅ 精选推荐文章 4265

【AI大模型】DeepSeek + Kimi 高效制作PPT实战详解

AI赋能,使用DeepSeek 高效制作PPT实战详解

congge 1万+

得意黑 Smiley Sans 免费商用标题黑体:8335 汉字、单字重、100+ 语言

得意黑 Smiley Sans 是一款字身窄而带斜势的开源中文黑体,SIL OFL 1.1 授权、可免费下载用于商业场景。本文讲清它适合与不适合的用法、8335 个汉字等关键规格、桌面与网页两条最短安装路径,以及 `路径`,以及 20 余条 OpenType 特性标签各自解决什么问题,看完即可决定要不要把它放进你的标题字库。 ## 🧭 先划边界:该用在哪、不该用在哪 得意黑的字身窄且整体偏斜

gitblog_00478的博客 876

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

RabbitMQ消息队列从入门到实践:核心概念、安装配置与高可用集群部署

消息队列(Message Queue)是解决分布式系统中生产者与消费者之间耦合与协调问题的核心技术,其核心原理在于通过异步通信机制实现解耦、削峰填谷和流量控制。在技术价值层面,它提升了系统的可扩展性、可靠性和响应能力,广泛应用于微服务通信、订单处理、日志收集等企业级应用场景。本文聚焦于AMQP协议的代表实现RabbitMQ,深入解析其核心组件如交换机(Exchange)、队列(Queue)和绑定(Binding),并涵盖高可用集群与镜像队列的部署实践,帮助开发者构建稳定高效的消息驱动架构。

weixin_33860528的博客 406

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

RabbitMQ核心配置实战:从连接管理到队列策略的稳定性保障

消息队列作为分布式系统异步通信和解耦的核心组件,其配置优化直接决定了系统的可靠性与性能表现。理解消息队列的工作原理,需要从生产者-消费者模型、消息持久化、流量控制等基础概念入手。在技术实现层面,合理的配置能够平衡消息传递的可靠性与系统吞吐量,例如通过预取计数(Prefetch Count)实现消费者端的流量控制,利用死信队列(DLX/DLQ)机制处理异常消息,保障关键业务数据的最终可达性。这些配置项共同构成了消息中间件的韧性基础,广泛应用于电商订单处理、支付结算、日志收集等对数据一致性和系统稳定性要求较高的

weixin_30527323的博客 314

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

RabbitMQ核心架构与实战:从消息队列原理到微服务解耦应用

消息队列作为分布式系统中的关键中间件,其核心原理在于实现应用间的异步通信和解耦。通过生产者-消费者模型,消息队列将消息的发送与接收分离,有效解决了系统间直接调用的耦合性问题,提升了系统的可扩展性和可靠性。在技术实现上,消息队列基于高级消息队列协议(AMQP)等标准,提供了可靠的消息传递、路由和存储机制。其技术价值主要体现在流量削峰、异步处理和系统解耦三大场景,能够显著提升高并发系统的稳定性和响应速度。在微服务架构和分布式系统中,消息队列常用于订单处理、日志收集、事件通知等场景。以RabbitMQ为例,它通过

weixin_34166847的博客 350

RabbitMQ学习笔记:消费者预取消息(basic.qos)

消费者预取是信道预取机制的扩展 AMQP 0-9-1协议指定basic.qos方法,以便在使用时限制channel(connection)上未确认的消息数(也称之为“prefetch count”)。 不幸的是,信道不是这方面的理想范围,因为一个信道可能消费来自多个队列的信息,信道和队列需要为发送的每个消息互相协助,以确保他们不会超过限制。这在单台机器上会很慢,在集群中使用会更慢。 此外,对于...

OceanSky的专栏 4374

channel rabbitmq 配置_深入理解RabbitMQ中的prefetch_count参数

前提在某一次用户标签服务中大量用到异步流程,使用了RabbitMQ进行解耦。其中,为了提高消费者的处理效率针对了不同节点任务的消费者线程数和prefetch_count参数都做了调整和测试,得到一个相对合理的组合。这里深入分析一下prefetch_count参数在RabbitMQ中的作用。prefetch_count参数的含义先从AMQP(Advanced Message Queuing Prot...

weixin_39578457的博客 805

php下RabbitMQ 中的$channel->basic_qos()函数是干啥的?

通过设置预取计数,你可以控制 RabbitMQ 向消费者传递的消息数量,以确保消息在消费者端有序、逐个处理。这有助于平衡系统负载,防止某一消费者一次性接收到过多的消息。是用来设置消费者的预取计数(prefetch count)的函数。预取计数指的是消费者在收到确认之前可以接收的未确认消息的最大数量。这样可以确保每个消费者在确认之前只会接收一条消息,从而确保了消息的顺序处理。这个函数通常在消费者端初始化时调用,以确保消息的有序处理。,即每个消费者可以同时处理的未确认消息的数量。在 RabbitMQ 中,

qq_28979487的博客 831
上一篇: RabbitMQ(五)高可用 -- Highly Available Queues
下一篇: RabbitMQ(七)心跳控制 -- heartbeat
笑天居士
博客等级 码龄24年 292粉丝 136原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值