上一篇讲了简单队列,实际工作中,这种队列应该很少用到,因为生产者发送消息的耗时一般都很短,但是消费者收到消息后,往往伴随着对高消息的业务逻辑处理,是个耗时的过程,这势必会导致大量的消息积压在一个消费者手中,从而导致业务的积压.

所以我们需要多个消费者一起消费队列中的消息,模型如下:(为了方便讲解,暂时隐藏掉"交换机")

生产者

    public class Producer
{
private const string QueueName = "test_work_queue";
public static void Send()
{
//获取一个连接
using (IConnection connection = ConnectionHelper.GetConnection())
{
//从连接中获取一个信道
using (IModel channel = connection.CreateModel())
{
//声明队列
channel.QueueDeclare(QueueName, false, false, false, null); for (int i = ; i < ; i++)
{
//创建消息
string msg = "hello world " + i;
//发送消息
channel.BasicPublish("", QueueName, null, Encoding.Default.GetBytes(msg));
Console.WriteLine($"{DateTime.Now} : send {msg}");
}
}
}
}
}

消费者1

    public class Consumer1
{
private const string QueueName = "test_work_queue";
public static void Receive()
{
//获取一个连接
IConnection connection = ConnectionHelper.GetConnection(); //从连接中获取一个信道
IModel channel = connection.CreateModel(); //声明队列
channel.QueueDeclare(QueueName, false, false, false, null); //添加消费者
EventingBasicConsumer consumer = new EventingBasicConsumer(channel); //注册消费者收消息事件
consumer.Received += (s, e) =>
{
byte[] bytes = e.Body;
string str = Encoding.Default.GetString(bytes);
Console.WriteLine("consumer1 receive : " + str);
Thread.Sleep();//休息0.5秒
}; //开启消费者监听
channel.BasicConsume(QueueName, true, "", false, false, null, consumer);
}
}

消费者2

只有一点点区别:

                Console.WriteLine("consumer2 receive : " + str);
Thread.Sleep();//休息1秒

我们这里故意让两个消费者处理消息的耗时不一样,一个0.5秒,一个1秒.

我们来看看结果:

可以非常清楚的看到,尽管两个消费者处理消息的"耗时"不一样,但是处理的"数量"是一样的.

这里有几个细节要说明一下:

1.在生产者和两个消费者中都声明了同一个队列.其实,如果这个队列之前已经存在了,那么生产者和消费者都可以不用再声明了;

2.一定要先启动两个消费者,再启动生产者.原因是,我们上面的代码中,消费者的 BasicConsume 方法的第2个参数传入的是 true,

这个参数就是 autoAck :是否自动确认(上面文章有讲过).

所以如果先开启生产者,那么会瞬间发送完50条消息,这时候启动消费者1,那么会立刻"消费"掉这50条消息.有朋友肯定要问,不是"睡"了0.5秒么?

这里"睡"0.5秒,是对消息的业务逻辑处理耗时,而不是"消费"消息,消息已经在消费者启动的那一刻从队列中"拿"过来了;

同时,由于采用的是"自动确认",所以队列看到50条都被"确认"了,就会将这些消息从队列中移除.

这时候再启动消费者2,则不会收到任何消息.

RabbitMQ (三) 工作队列之轮询分发的更多相关文章

  1. RabbitMQ学习第二记:工作队列的两种分发方式,轮询分发(Round-robin)和 公平分发(Fair dispatch)

    1.什么是RabbitMQ工作队列 我们在应用程序使用消息系统时,一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据.因此如果一 ...

  2. RabbitMQ基本示例,轮询机制,no_ack作用

    一.RabbitMQ简介: ''' RabbitMQ就是消息队列 之前不是学了Queue了吗,都是队列还学RabbitMQ干嘛? 干的事情是一样的 Python的Queue有两个, 一个线程Queue ...

  3. demo rabbitmq topic(主题模式),fanout(广播模式),轮询分发,确认接收Ack处理

    //durable = true 代表持久化 交换机和队列都要为true ,持久代表服务重启,没有处理的消息依然存在 //topic 根据不同的routkey 发送和接收信息 //fanout 广播模 ...

  4. RabbitMQ的轮询模式和公平分发

    一.常用的消息模式 我们在工作的使用中,经常会遇到多个消费者监听同一个队列的情况,模型如下图所示: 当有多个消费者时,我们的消息会被哪个消费者消费呢,我们又该如何均衡消费者消费信息的多少呢: 主要有两 ...

  5. RabbitMQ (四) 工作队列之公平分发

    上篇文章讲的轮询分发 : 1个队列,无论多少个消费者,无论消费者处理消息的耗时长短,大家消费的数量都一样. 而公平分发,又叫 : 能者多劳,顾名思义,处理得越快,消费得越多. 生产者 public c ...

  6. php和ajax 服务器端做轮询推送(定义)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  7. Web 通信 之 长连接、长轮询(转)

    Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强 ...

  8. Web 通信 之 长连接、长轮询(long polling)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  9. nginx负载均衡 加权轮询和ip_hash

    下面给大家总结了几种真正的nginx负载均衡的功能了,在此我们加了一个权重判断法就是根据nginx负载的状态实现分配访问用户到权重值少的机器了,具体配置如下. nginx为后端web服务器(apach ...

随机推荐

  1. [洛谷P1251]餐巾计划问题

    题目大意:一个餐厅N天,每天需要$r_i$块餐巾.每块餐巾需要p元,每天用过的餐巾变脏,不能直接用.现在有快洗店和慢洗店,快洗店洗餐巾需要m天,每块花费f元:慢洗店洗餐巾需要n天,每块餐巾s元(m & ...

  2. [poj 3252]数位dp前导0的处理

    通过这个题对于数位dp中前导0的处理有了新的认识. 题目链接:http://poj.org/problem?id=3252 //http://poj.org/problem?id=3252 #incl ...

  3. POJ 2398 Toy Storage 二分+叉积

    Description Mom and dad have a problem: their child, Reza, never puts his toys away when he is finis ...

  4. LwIP - 打开keepalive功能

    在服务器端打开keepalive功能 1.保证LWIP_TCP_KEEPALIVE被定义为1,(这样TCP_KEEPIDLE.TCP_KEEPINTVL和TCP_KEEPCNT 设置才有效) 2. i ...

  5. hive对有特殊值null的数据倾斜处理

    对有特殊值的数据倾斜处理 SET mapred.reduce.tasks=20;SET hive.map.aggr=TRUE;SET hive.groupby.skewindata=TRUE;SET ...

  6. PHP正则替换preg_replace函数的使用

    <?php $str="as2223adfsf0s4df0sdfsdf"; echo preg_replace("/0/","",$s ...

  7. Spring学习--基于 XML 的配置声明切面

    正常情况下 , 基于注解的生命要优先于基于 XML 的声明. 通过 AspectJ 注解 , 切面可以与 AspectJ 兼容 , 而基于 XML 的配置则是 Spring 专有的.由于 Aspect ...

  8. Cannot read property 'resetFields' of undefined 问题及引申

    问题描述: 使用element开发我的后台系统,编辑和新增使用了同一个弹出框<el-dialog><el-form></el-form></el-dialog ...

  9. POJ1182 食物链---(经典种类并查集)

    题目链接:http://poj.org/problem?id=1182   食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

  10. Windows下使用批处理实现启动关闭mysql_DOS/BAT

    cls @echo off :设置窗口字体颜色 color 0a :设置窗口标题 TITLE MySQL管理程序 by ThinkVenus call :checkAdmin goto menu :菜 ...