RabbitMQ(四)——工作队列模式
RabbitMQ系列
RabbitMQ(四)——工作队列模式
前言
工作队列模式:
一个生产者,多个消费者,每个消费者获取到的消息唯一,当您运行多个工作线程,这些消息将在工作线程之间共享,默认轮询获取。简单的说,工作队列模式和简单模式一样,只是简单模式一个生产者一个消费者一对一,而工作队列模式一个生产者多个消费者。
这里启动三个线程,分别为生产者,消费者1,消费者2其中生产者和消费者代码与上一篇简单模式基本一致,稍作修改
实现
生产者:

static void Main(string[] args) { //1.创建连接工厂 ConnectionFactory factory = new ConnectionFactory() { HostName = "127.0.0.1", UserName = "guest", Password = "guest" }; //2.创建连接 var connection = factory.CreateConnection(); //3.创建管道 var channel = connection.CreateModel(); //4.声明队列 channel.QueueDeclare("simple", false, false, false, null); for (int i = 0; i < 20; i++) { string msg = $"第{i + 1}条消息"; //5.发布消息 channel.BasicPublish("", "simple", null, Encoding.UTF8.GetBytes(msg)); Console.WriteLine($"已发送消息:{msg}"); Thread.Sleep(1000); } channel.Close(); connection.Close(); Console.ReadKey(); }
消费者1、2:

static void Main(string[] args) { //初始化工厂 ConnectionFactory factory = new ConnectionFactory() { HostName = "127.0.0.1", UserName = "guest", Password = "guest" }; //创建连接 using (IConnection connection = factory.CreateConnection()) { using (IModel channel = connection.CreateModel()) { //声明队列 channel.QueueDeclare("simple", false, false, false, null); //创建消费者对象 var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, e) => { byte[] message = e.Body.ToArray(); Console.WriteLine("接收消息:" + Encoding.UTF8.GetString(message)); //返回消息确认 channel.BasicAck(e.DeliveryTag, false); }; //消费者开启监听 channel.BasicConsume("simple", false, consumer); Console.ReadLine(); } } }
结果
这时消费者P向队列写入消息,消费者1和消费者2会公平调度,如下:
可以看到一个消费者接收到单数消息,另一个消费者接收到双数消息。这种情况是因为RabbitMQ在进入队列后就开始分发消息,它不会去检查每个消费者是否拥有未确认的消息数量,只是盲目的给每个消费者平均分发。
消息调度
现在我们改变这种行为,设置BasicQos
1 | IModel.BasicQos(0,1, false ); |
这表示让RabbitMQ不给这个消费者发送新的消息,直到消费者处理并确认了前一个消息。当消费者1的消息没确认,那么将跳过消费者1,向消费者2发送。
消费者代码现在是这样:

static void Main(string[] args) { //初始化工厂 ConnectionFactory factory = new ConnectionFactory() { HostName = "127.0.0.1", UserName = "guest", Password = "guest" }; //创建连接 using (IConnection connection = factory.CreateConnection()) { using (IModel channel = connection.CreateModel()) { //声明队列 channel.QueueDeclare("simple", false, false, false, null); // 告知 RabbitMQ,在未收到当前 Worker 的消息确认信号时,不再分发给消息,确保公平调度。 channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); //创建消费者对象 var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, e) => { byte[] message = e.Body.ToArray(); Console.WriteLine("接收消息:" + Encoding.UTF8.GetString(message)); //返回消息确认 channel.BasicAck(e.DeliveryTag, false); }; //消费者开启监听 channel.BasicConsume("simple", false, consumer); Console.ReadLine(); } } }
可以看到,现在的消息接收是哪个消费者空闲(处理完成并确认消息)就给哪个发送消息,所以消息顺序不再是一个消费者接收单数消息,一个消费者接收双数消息。
附上Demo地址:https://github.com/1164887865/RabbitMQDemo
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现