RabbitMQ入门-竞争消费者模式
上一篇讲了个 哈喽World,现在来看看如果存在多个消费者的情况。
生产者:
package com.example.demo; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; import java.io.IOException;
import java.util.concurrent.TimeoutException; /**
* 竞争消费者模式
*/
public class CompetingSend { private static final String QUEUE_NAME = "hello"; public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory(); // 连接工厂
factory.setHost("localhost");
Connection connection = factory.newConnection(); // 获取连接
Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 声明队列,只有他不存在的时候创建
String msg = "Hello World!";
// 发送多条消息
for (int i = 0; i < 5; i++){
channel.basicPublish("", QUEUE_NAME, null, (msg + "-" + i).getBytes());
System.out.println("Sending:" + msg);
} channel.close();
connection.close(); }
}
消费者:
package com.example.demo; import com.rabbitmq.client.*; import java.io.IOException;
import java.util.concurrent.TimeoutException; /**
* 一个生产者,多个消费者
*/
public class CompetingReceiveA { private static final String QUEUE_NAME = "hello"; public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory(); // 连接工厂
factory.setHost("localhost");
Connection connection = factory.newConnection(); // 获取连接
Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 声明队列,只有他不存在的时候创建 Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String recv = new String(body, "UTF-8");
System.out.println("Receive:" + recv);
try {
doWork(recv);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("Done");
}
}
}; // true代表接收到消息后,给兔子发消息,让这条消息失效
channel.basicConsume(QUEUE_NAME, true, consumer);
} // 模拟每条消息处理时间不一样
private static void doWork(String msg) throws InterruptedException {
char c = msg.charAt(msg.length() - 1);
for (int i = 0; i < Integer.parseInt(c+""); i++)
Thread.sleep(1000);
} }
先启动两个消费者,再启动生产者,查看控制台:
消费者A

消费者B

生产者(这里不必有疑问,这里打印的是修改之前的消息)

要说明的是什么观点呢?
默认情况下,RabbitMQ将按顺序将每条消息发送给下一个使用者。一般来说,每个消费者得到的消息是一样多。但是,并不是说每个消费者的任务重量是平均的。很有可能出现A总在处理耗时任务,B一直吃西瓜的情况。
因为兔子不知道每个消息的耗时,他就会傻傻的派遣任务。
不过,官方也有解决办法。
为了解决这个问题,我们可以使用basicQos方法,设置prefetchCount = 。这告诉RabbitMQ不要向消费者发送多于一条消息。换句话说,在它处理并确认了前一个消息之前,不要向工作人员发送新消息。
如果当前消费者正在忙碌(没有确认消息),它会将其分派给空闲下一个消费者。
int prefetchCount = 1;
channel.basicQos(prefetchCount);
RabbitMQ入门-竞争消费者模式的更多相关文章
- RabbitMQ入门-消息订阅模式
消息派发 上篇<RabbitMQ入门-消息派发那些事儿>发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理. 楼主,有遇到消费者后台进程不在,但consumer连接 ...
- Competing Consumers Pattern (竞争消费者模式)
Enable multiple concurrent consumers to process messages received on the same messaging channel. Thi ...
- RabbitMQ入门-发布订阅模式
兔子的Publish/Subscribe是这样的: 有个生产者P,X代表交换机,交换机绑定队列,消费者从队列中取得消息.每次有消息,先发到交换机中,然后由交换机负责发送到它已知的队列中. 生产者代码: ...
- RabbitMQ入门到进阶(Spring整合RabbitMQ&SpringBoot整合RabbitMQ)
1.MQ简介 MQ 全称为 Message Queue,是在消息的传输过程中保存消息的容器.多用于分布式系统 之间进行通信. 2.为什么要用 MQ 1.流量消峰 没使用MQ 使用了MQ 2.应用解耦 ...
- RabbitMQ详解(三)------RabbitMQ的五种模式
RabbitMQ详解(三)------RabbitMQ的五种模式 1.简单队列(模式) 上一篇文章末尾的实例给出的代码就是简单模式. 一个生产者对应一个消费者!!! pom.xml 必须导入Rab ...
- RabbitMQ入门案例
RabbitMQ入门案例 Rabbit 模式 https://www.rabbitmq.com/getstarted.html 实现步骤 构建一个 maven工程 导入 rabbitmq的依赖 启动 ...
- SpringBoot整合RabbitMQ实现六种工作模式
RabbitMQ主要有六种种工作模式,本文整合SpringBoot分别介绍工作模式的实现. 前提概念 生产者 消息生产者或者发送者,使用P表示: 队列 消息从生产端发送到消费端,一定要通过队列转发,使 ...
- RabbitMQ入门-高效的Work模式
扛不住的Hello World模式 上篇<RabbitMQ入门-从HelloWorld开始>介绍了RabbitMQ中最基本的Hello World模型.正如其名,Hello World模型 ...
- RabbitMQ入门-Topic模式
上篇<RabbitMQ入门-Routing直连模式>我们介绍了可以定向发送消息,并可以根据自定义规则派发消息.看起来,这个Routing模式已经算灵活的了,但是,这还不够,我们还有更加多样 ...
随机推荐
- Web API 2 使用Entity Framework Part 1.
创建项目 打开Visual Studio,选择ASP.NET Web Application,项目名称BookService并点击OK. 选择Web API 模板 如果你想使用Azure App Se ...
- AMD三代锐龙箭在弦上:如此家族堪称豪华
AMD将于今年年中正式推出第三代Ryzen锐龙处理器,即不集成显示芯片的纯CPU产品,外界猜测可能的时间点会是5月底的台北电脑展. 虽说依然采用AM4接口,也就是X370/470老主板可无压力兼容,但 ...
- Django通用视图APIView和视图集ViewSet的介绍和使用
原 Django通用视图APIView和视图集ViewSet的介绍和使用 2018年10月21日 14:42:14 不睡觉假扮古尔丹 阅读数:630 1.APIView DRF框架的视图的基类是 ...
- java 转义字符"\u0010" "\010" "\2"等
java转义字符 \xxx 八进制转义符 \uxxxx 十六进制转义符 像"\010","\u0010"这种字符 ...
- winserver 2008 R2服务器安装IIS
winserver 2008 R2 IIS7 安装IIS 打开服务器管理器 选择“角色”,右击添加角色 点击“下一步” 勾选”Web服务器(IIS)“,点击”下一步“ 勾选”常见Http功能.应用程序 ...
- P1164 小A点菜
原题链接 https://www.luogu.org/problemnew/show/P1164 此题是一道简单的动规问题 才学两天不是很熟练,我苦思冥想看着题解终于想出来了. 主要的思路如下: 我们 ...
- River Problem HDU - 3947(公式建边)
River Problem Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...
- Ionic的NavController 和ModalController 的区别
网上也没有找到直接介绍两者区别的文章,以下都是个人感觉 区别 NavController 和 ModalController 都是打开新页面,但是NavController 是直接将页面放入到原有的页 ...
- opencv 图片剪切
import cv2 as cv import numpy as np # 图片剪切 img = cv.imread('../images/moon.jpg', flags=1) # flags=1读 ...
- Leetcode 202.快乐数 By Python
编写一个算法来判断一个数是不是"快乐数". 一个"快乐数"定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 ...