由于在实际应用中,简单队列模型无法解决很多实际问题,而且生产者和消费者是一对一的关系。模型较为单一。故引入Work模式。

结构图

一个生产者、多个消费者。
一个消息只能被一个消费者获取。

测试实现: 
1、生产者

 private final static String QUEUE_NAME = "test_queue_work";

    public static void main(String[] argv) throws Exception {
// 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel(); // 声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null); for (int i = 0; i < 50; i++) {
// 消息内容
String message = "" + i;
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'"); Thread.sleep(i * 10);
} channel.close();
connection.close();
}

生产者循环创建消息 
2、消费者一

private final static String QUEUE_NAME = "test_queue_work";

    public static void main(String[] argv) throws Exception {

        // 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel(); // 声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 同一时刻服务器只会发一条消息给消费者
channel.basicQos(1); // 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列,手动返回完成
channel.basicConsume(QUEUE_NAME, false, consumer); // 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
//休眠
Thread.sleep(10);
// 返回确认状态
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}

3、消费者二 
注意:channel.basicQos(1); 被注释掉了

private final static String QUEUE_NAME = "test_queue_work";

    public static void main(String[] argv) throws Exception {

        // 获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel(); // 声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 同一时刻服务器只会发一条消息给消费者
// channel.basicQos(1); // 定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 监听队列,手动返回完成状态
channel.basicConsume(QUEUE_NAME, false, consumer); // 获取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
// 休眠1秒
Thread.sleep(1000); channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}

测试结果:

1、 消费者1和消费者2获取到的消息内容是不同的,同一个消息只能被一个消费者获取。 
2、 消费者1和消费者2获取到的消息的数量是相同的,一个是奇数一个是偶数。

其实,这样是不合理的,应该是消费者1要比消费者2获取到的消息多才对。

消息的确认模式

消费者从队列中获取消息,服务端如何知道消息已经被消费呢?

模式1:自动确认

只要消息从队列中获取,无论消费者获取到消息后是否成功消息,都认为是消息已经成功消费。

模式2:手动确认

消费者从队列中获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,如果消费者一直没有反馈,那么该消息将一直处于不可用状态。

应用场景

集群中同时监听一个服务队列

RabbitMQ五种消息队列学习(三)–Work模式的更多相关文章

  1. Rabbit五种消息队列学习(一) – 总述

    RabbitMQ支持五种消息传递类型,分别如下图所示: 上图中显示6中消息队列分别为: 1.简单队列 一个生产者将消息放到队列中,一个消费者监听队列 2.工作队列(Work queues) 一个生产者 ...

  2. Rabbit五种消息队列学习(二) – 简单队列

    队列结构图 P:消息的生产者 C:消息的消费者 红色:队列 生产者将消息发送到队列,消费者从队列中获取消息. 测试 1.连接MQ public static Connection getConnect ...

  3. 学习ActiveMQ(五):activemq的五种消息类型和三种监听器类型

    一.前面我们一直发送的是字符串类型,其实activemq一共支持五种消息类型: 1.String消息类型:发送者:消费者: 1.String消息类型:发送者:消费者: 1.String消息类型:发送者 ...

  4. rabbitmq五种消息模型整理

    目录 0. 配置项目 1. 基本消息模型 1.1 生产者发送消息 1.2 消费者获取消息(自动ACK) 1.3 消息确认机制(ACK) 1.4 消费者获取消息(手动ACK) 1.5 自动ACK存在的问 ...

  5. RabbitMQ,RocketMQ,Kafka 几种消息队列的对比

    常用的几款消息队列的对比 前言 RabbitMQ 优点 缺点 RocketMQ 优点 缺点 Kafka 优点 缺点 如何选择合适的消息队列 参考 常用的几款消息队列的对比 前言 消息队列的作用: 1. ...

  6. RabbitMQ之五种消息模型

    首先什么是MQ MQ全称是Message Queue,即消息对列!消息队列是典型的:生产者.消费者模型.生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息.因为消息的生产和消费都是异步的,而 ...

  7. (八)RabbitMQ消息队列-通过Topic主题模式分发消息

    原文:(八)RabbitMQ消息队列-通过Topic主题模式分发消息 前两章我们讲了RabbitMQ的direct模式和fanout模式,本章介绍topic主题模式的应用.如果对direct模式下通过 ...

  8. RabbitMQ AMQP (高级消息队列协议)

    目录 RabbitMQ AMQP (高级消息队列协议) Message Queue 简介 概念 基本组成 场景及作用 AMQP简介 模型架构 基础组件 AMQP-RabbitMQ 简介 模型 特性 参 ...

  9. 第二百九十一节,RabbitMQ多设备消息队列-安装与简介

    RabbitMQ多设备消息队列-安装与简介 RabbitMQ简介 解释RabbitMQ,就不得不提到AMQP(Advanced Message Queuing Protocol)协议. AMQP协议是 ...

随机推荐

  1. 轻松3步设置sublime text2/sublime text3的预览浏览器

    转https://www.cnblogs.com/swii/p/5888494.html 1,打开sublime 依次选择 tools > build system > new build ...

  2. 网络编程-线程-3、通过继承Thread类创建线程

    知识点:之前第一节介绍创建线程的方法是:通过threading.Thread(target=函数名不要加括号)创建一个对象,通过对象调用start方法创建并启动线程:                  ...

  3. Linux学习之源码包安装与脚本安装(十八)

    Linux学习之源码包安装与脚本安装 目录 源码包与RPM包的区别 源码包安装 脚本安装 源码包与RPM包的区别 1.区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 源码包: 开源的 ...

  4. ftp服务器搭建流程详解

    随着项目的运行,项目的体积越来越庞大,于是将文件(这里包括所有上传的附件信息等)放在项目中已经显得很臃肿,项目运行的速度会越来越慢,逐步制约了项目的用户体验,为解决这一问题我们可以将项目剥离开来,让多 ...

  5. re模块、hashlib模块

    一.re模块 1.什么是正则? 正则就是用一系列具有特殊含义的字符组成一套规则,该规则用来描述具有某一特征的字符串,正则就是用来去一个大的字符串中匹配出符合规则的子字符串 2.为何要用正则? 用户注册 ...

  6. 伪类实现特殊图形,一个span加三角形

    题目如图: 实现思路: 伪类+三边透明的三角形实现 代码: <span class="wei">wei</span> .wei{ display: inli ...

  7. AGC 005D.~K Perm Counting(容斥 DP 二分图)

    题目链接 \(Description\) 给定\(n,k\),求 满足对于所有\(i\),\(|a_i-i|\neq k\)的排列的个数. \(2\leq n\leq 2000,\quad 1\leq ...

  8. 【开源GPS追踪】 之 服务器硬伤

    前面就说过了,目前GPS 追踪的原理都是通过GPRS将数据发送到一个服务器上,如果回看数据就从服务器上去数据,服务器在整个系统中具有举足轻重的地位. 如果服务器坏了,整个系统几千台设备可能也就无法工作 ...

  9. 【开源GPS追踪】 之 硬件开源

    根据设定目标: 使用GPS 采集经纬度,然后通过GPRS模块/wifi 发送到服务器显示,WIFI不常有,所有就使用GPRS模块! 对于GPS模块,没有特殊要求,只要输出格式符合NMEA协议即可,为了 ...

  10. 潭州课堂25班:Ph201805201 django 项目 第二十七课 docker简介,配置文件 (课堂笔记)

    新闻搜索功能实现 一.docker介绍 1.什么是docker? 使用容器让创建.部署.运行应用程序更简单的一个工具 让应用所需的库和依赖环境打包 有一点点像虚拟机 2.为什么使用docker? 3. ...