Rabbit MQ 基础入门
Rabbit MQ 学习(一)基础入门
简介
RabbitMQ 简介
在介绍 RabbitMQ 之前实现要介绍一下MQ,MQ 是什么?MQ 全称是 Message Queue,可以理解为消息队列的意思,简单来说就是消息以管道的方式进行传递。RabbitMQ 是一个实现了AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,用 Erlang 语言的。
为什么选择 RabbitMQ
1.RabbitMQ 实现了 AMQP 标准的消息服务器;
2.可靠性,RabbitMQ 的持久化支持,保证了消息的稳定性;
3.高并发,RabbitMQ 使用了 Erlang 开发语言,Erlang 是为电话交换机开发的语言,天生自带高并发光环,和高可用特性;
4.集群部署简单,正是应为 Erlang 使得 RabbitMQ 集群部署变的超级简单;
5.社区活跃度高,根据网上资料来看,RabbitMQ 也是首选;
RabbitMQ 的模型架构是什么?
RabbitMQ 整体上是一个生产者与消费者模型,主要负责存储和转发消息。我们可以把 RabbitMQ 想象成一个快递站,我们需要邮寄包裹需要把包裹送到快递站,快递站会暂存并最终通过快递员来把包裹送到收件人的手上。RabbitMQ 就好比是快递站和快递员组成的一个系统。

AMQP 协议是什么?
AMQP 协议本身包括三层
1.Module Layer:位于协议最高层,主要定义客户端调用的命令。例如 Queue.Declare 命令声明一个队列或者使用 Basic.Consume 订阅消费一个队列中的消息。
2.Session Layer:位于中间层,主要负责将客户端的命令发送给服务器,再将服务器的应答返回给客户端。主要为客户端与服务器之间的通信提供可靠性同步机制和错误处理。
3.Transport Layer:位于最底层,主要传输二进制数据流,提供帧的处理、信道复用、错误检测和数据表示等。
AMQP 其本质还是一个通信协议,通信协议都会涉及报文交互,从简单了说 AMQP 本身就是应用层协议是 TCP 协议的数据部分。从复杂了说 AMQP 是通过协议命令进行交互的,可以看作是一系列命令的集合操作。
AMQP 常用命令
| 名称 | 是否包含内容体 | 对应客户端中的方法 | 简要描述 |
|---|---|---|---|
| Connection.start | 否 | factory.newConnection | 建立连接相关 |
| Connection.Start-Ok | 否 | 同上 | 同上 |
| Connection.Tune | 否 | 同上 | 同上 |
| Connection.Tune-Ok | 否 | 同上 | 同上 |
| Connection.Open | 否 | 同上 | 同上 |
| Connection.Open-Ok | 否 | 同上 | 同上 |
| Connection.Close | 否 | connection.close | 关闭连接 |
| Connection.Close-Ok | 否 | 同上 | 同上 |
| Channel.Open | 否 | connection.openChannel | 开启信道 |
| Channel.Open-Ok | 否 | 同上 | 同上 |
| Cbannel.Close | 否 | channel.close | 关闭信道 |
| Channel.Close-Ok | 否 | 同上 | 同上 |
| Exchange.Declare | 否 | channel.exchangeDeclare | 声明交换器 |
| Exchange.Declare-Ok | 否 | 同上 | 同上 |
| Exchange.Delete | 否 | channel.exchangeDelete | 删除交换器 |
| Exchange.Delete-Ok | 否 | 向上 | 同上 |
| Exchange.Bind | 否 | channel.exchangeBind | 交换器与交换器绑定 |
| Exchange.Bind-Ok | 否 | 同上 | 同上 |
| Exchange.Unbind | 否 | channel.exchangeUnbind | 交换器与交换器解绑 |
| Exchange.Unbind-Ok | 否 | 同上 | 同上 |
| Queue.Declare | 否 | channel.queueDeclare | 声明队列 |
| Queue. Declare-Ok | 否 | 同上 | 同上 |
| Queue.Bind | 否 | channel.queueBind | 队列与交换器绑定 |
| Queue.Bind-Ok | 否 | 同上 | 同上 |
| Queue.Purge | 否 | channel.queuePurge | 清除队列中的内容 |
| Queue.Purge-Ok | 否 | 同上 | 同上 |
| Queue.Delete | 否 | channel.queueDelete | 删除队列 |
| Queue.Delete-Ok | 否 | 同上 | 向上 |
| Queue.Unbind | 否 | channel.queueUnbind | 队列与交换器解绑 |
| Queue.Unbind-Ok | 否 | 同上 | 同上 |
| Basic.Qos | 否 | channel.basicQos | 设置未被确认消费的个数 |
| Basic.Qos-Ok | 否 | 同上 | 同上 |
| Basic.Consume | 否 | channel.basicConsume | 消费消息(推模式) |
| Ba siιCo nsurne-Ok | 否 | 同上 | 同上 |
| Basic.Cancel | 否 | channel.basicCancel | 取消 |
| Basic.Cancel-Ok | 否 | 同上 | 同上 |
| Basic.Publish | 是 | channel.basicPublish | 发送消息 |
| Basic.Return | 是 | 无 | 未能成功路由的消息返回 |
| Basic.Deliver | 是 | 无 | Broker 推送消息 |
| Basic.Get | 否 | channel.basicGet | 消费消息(拉模式) |
| Basic.Get-Ok | 是 | 同上 | 同上 |
| Basic.Ack | 否 | channel.basicAck | 确认 |
| Basic.Reject | 否 | channel.basicReject | 拒绝(单条拒绝) |
| Basic.Recover | 否 | channel.basicRecover | 请求 Broker 重新发送未被确认的消息 |
| Basic.Recover-Ok | 否 | 同上 | 同上 |
| Basic.Nack | 否 | channel.basicNack | 拒绝(可批量拒绝) |
| Tx.Select | 否 | channel. txSelect | 开启事务 |
| TX.Select-Ok | 否 | 同上 | 同上 |
| Tx.Cornmit | 否 | channel. txCommit | 事务提交 |
| TX.Commit-Ok | 否 | 同上 | 同上 |
| Tx.Rollback | 否 | channel.txRollback | 事务回滚 |
| TX.Rollback-Ok | 否 | 同上 | 同上 |
| Confirrn Select | 否 | channel.confinnSelect | 开启发送端确认模式 |
| Confinn.Select-Ok | 否 | 同上 | 同上 |
概念
生产者和消费者
Producer:生产者,就是投递消息的一方。
生产者创建消息然后发布到 RabbitMQ 中。消息一般可以包含两部分:标签和消息体。在实际应用中消息体一般是一个带有业务逻辑结构的数据,比如一个 json 字符串。消息的标签用来表述这条消息,比如一个交换器的名称和一个路由键。生产者将消息发布到 RabbitMQ,RabbitMQ 之后会根据标签把消息发送到感兴趣的消费者。
Consumer:消费者,就是接收消息的一方。
消费者连接到 RabbitMQ 服务器并订阅到队列上。当消费者消费一条消息时只是消费的消息体而不是标签,标签在消息路由过程中会丢弃。存入到队列中的只是消息体,消费者只会消费消息体。
Broker:消息中间件的服务节点。
一个 Broker 可以简单的看作是一个 RabbitMQ 服务节点或者 RabbitMQ 服务实例。

队列
Queue:队列,是 RabbitMQ 的内部对象,用于存储消息。

RabbitMQ 中消息只能存储在队列中,主题模式只是每个消费者申请一个队列和交换器绑定了。RabbitMQ 的生产者生产消息并最终投递到队列中,消费者可以从队列中获取消息并消费。
多个消费者也可以订阅到同一个队列,这时队列中的消息会被平均分摊(Round-Robin 轮询)给多个消费者进行处理,而不是每个消费者都收到同样的消息并处理,叫做工作队列。

交换器、路由键、绑定
Exchange:交换器,生产者将消息发送到 Exchange,由交换器将消息路由到一个或者多个队列中。

RabbitMQ 常用交换器类型有:fanout、direct、topic、headers 这四种
1.fanout:它会把所有发送到该交换机的消息路由到所有与该交换机绑定的队列中。
2.direct:它会把消息路由到那些 bindingKey 和 RoutingKey 完全匹配的队列中。
3.topic:topic 类型的交换器在匹配的规则上进行了扩展,与 direct 相似,但是匹配规则有些不同。
3.1.RoutingKey 为一个点号 “.” 分隔的字符串如 “com.rabbitmq.client”、“java.util.lang”、""。
3.2.BindingKey 和 RoutingKey 一样也是点号 “.” 分隔的字符串。
3.3.BindingKey 中可以存在两种特殊字符串 “" 和 “#”,用于做模糊匹配,其中 "” 用于匹配一个单词,"#" 用于匹配多规格单词(可以是零个)。

以上图为例
1.路由键为 “com.rabbitmq.client” 的消息会被路由到 Queue1 和 Queue2;
2.路由键为 “com.hidden.client” 的消息只会被路由到 Queue2 中;
3.路由键为 “com.hidden.demo” 的消息只会被路由到 Queue2 中;
4.路由键为 “java.rabbitmq.demo” 的消息只会路由到 Queue1 中;
5.路由键为 “java.util.concurrent” 的消息将会被丢弃或者返回给生产者(需要设置 mandatory 参数),因为它没有匹配任何路由键;
**RoutingKey:**路由键,生产者将消息发给交换机的时候,一般会指定一个路由键,用来指定消息路由规则,而这个路由键需要与交换机类型和绑定键联合使用才能生效。
**Binging:**绑定,RabbitMQ 中通过绑定将交换器与队列关联起来,在绑定的时候一般会指定一个绑定键,这样 RabbitMQ 就知道如何正确的将消息路由到队列了。

生产者将消息发送给交换器时,需要一个 RoutingKey ,当 BindingKey 和 RoutingKey 相匹配时,消息会被路由到对应的队列中。
RabbitMQ 运转流程,消息从生产者发出到消费者这一过程要经历一些什么?
了解了 RabbitMQ 的架构模型,我们来回顾下整个流程。
1.生产者发送消息
1.1.生产者连接到 RabbitMQ Broker ,建立一个连接(Connection) ,开启一个信道(Channel)
1.2.生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等
1.3.生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等
1.4.生产者通过路由键将交换器和队列绑定起来
1.5.生产者发送消息至 RabbitMQ Broker ,其中包含路由键、交换器等信息
1.6.相应的交换器根据接收到的路由键查找相匹配的队列
1.7.如果找到,则将从生产者发送过来的消息存入相应的队列中
1.8.如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
1.9.关闭信道
1.10.关闭连接
public class RabbitMqReview {
private static final String EXCHANGE_NAME = "test_exchange_any_type";
private static final String QUEUE_NAME = "hello_word";
public static void main(String[] args) throws IOException, TimeoutException {
// 声明连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 使用连接工厂赋值 userName、password、host、vHost、port 等等
factory.setUsername("userName");
factory.setPassword("userName");
factory.setHost("host");
factory.setVirtualHost("vhost");
factory.setPort(5672);
// 创建连接
Connection conn = factory.newConnection();
System.out.println("RabbitMqReview 获取到的链接是: " + conn);
// 创建通道
Channel channel = conn.createChannel();
System.out.println("RabbitMqReview 获取到的通道是: " + channel);
// 声明一个交换器
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
// 声明一个队列
// channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 发送消息
String message = "Hello Word!";
channel.basicPublish(EXCHANGE_NAME, "routingKey", MessageProperties.TEXT_PLAIN, message.getBytes());
// 关闭资源
channel.close();
conn.close();
}
}
2.消费者接收消息
2.1.消费者连接到 RabbitMQ Broker,建立一个连接(Connection),开启一个信道(Channel)
2.2.消费者向 RabbitMQ Broker 请求消费相应队列中的消息
2.3.等待 RabbitMQ Broker 回应并投递相应队列中的消息,消费者接收消息
2.4.消费者确认(ack) 接收到的消息
2.5.RabbitMQ 从队列中删除相应己经被确认的消息
2.6.关闭信道
2.7.关闭连接
public class RabbitMqRecReview {
private static final String EXCHANGE_NAME = "test_exchange_any_type";
private static final String QUEUE_NAME = "hello_word";
public static void main(String[] args) throws IOException, TimeoutException {
// 声明连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 使用连接工厂赋值 userName、password、host、vHost、port 等等
factory.setUsername("userName");
factory.setPassword("userName");
factory.setHost("host");
factory.setVirtualHost("vhost");
factory.setPort(5672);
// 创建连接
Connection conn = factory.newConnection();
System.out.println("RabbitMqRecReview 获取到的链接是: " + conn);
// 创建通道
Channel channel = conn.createChannel();
System.out.println("RabbitMqRecReview 获取到的通道是: " + channel);
// 声明一个交换器
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
// 绑定对应的队列
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "bindingKey");
// 声明消费回调函数
DeliverCallback deliverCallback = new DeliverCallback() {
@Override public void handle(String s, Delivery delivery) throws IOException {
System.out.println("RabbitMqRecReview receive: " + new String(delivery.getBody(), StandardCharsets.UTF_8));
// 确认(ack)接收到的消息
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
};
channel.basicConsume(QUEUE_NAME, false, deliverCallback, new CancelCallback() {
@Override public void handle(String s) throws IOException {
}
});
}
}
Connection 和 Channel
无论生产者和消费者都需要和 RabbitMQ Broker 建立连接,这个连接就是一条 TCP 连接,也就是 Connection。一旦 TCP 连接建立成功,紧接着需要创建一个 AMQP 的信道(Channel),每条信道都会被指派一个唯一的 ID。信道是建立在 Connection 之上的虚拟连接,RabbitMQ 处理的每条 AMQP 指令都是通过信道完成的。


以上介绍了生产者(Producer ) 、消费者(Consumer) 、队列(Queue) 、交换器(Exchange)、路由键(RoutingKey )、绑定(Binding)、连接(Connection)和信道(Channel) 。
Rabbit MQ 基础入门的更多相关文章
- spring boot 中 rabbit mq基础例子
1.先安装ELANG,再按照RabbitMQ 2.打开RabbitMQ控制台:rabbit command prompt 1.设置elang的路径:set ERLANG_HOME=D:\work_pr ...
- rabbit mq 基础流程(转)
从AMQP协议可以看出,MessageQueue.Exchange和Binding构成了AMQP协议的核心,下面我们就围绕这三个主要组件 从应用使用的角度全面的介绍如何利用Rabbit MQ构建 ...
- Rabbit MQ 入门指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
- ASP.NET Core消息队列RabbitMQ基础入门实战演练
一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...
- rabbitmq(一)-基础入门
原文地址:https://www.jianshu.com/p/e186a7fce8cc 在学东西之前,我们先有一个方法论,知道如何学习.学习一个东西一般都遵循以下几个环节: xxx是什么,诞生的原因, ...
- 在 Windows 上安装Rabbit MQ 指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
- (转)在 Windows 上安装Rabbit MQ 指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
- celery rabbit mq 详解
Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, ...
- Rabbit MQ 消息确认和持久化机制
一:确认种类 RabbitMQ的消息确认有两种.一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是确认是否到 ...
随机推荐
- ubuntu终端仿真程序和文件管理程序
1.SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单的说是Windows下登录UNIX或Linux服务器主机的软件.可以理解为ubuntu下的Terminal. 如果Sec ...
- STM32嵌入式开发学习笔记(七):串口通信(下)
下面我们进行几个串口通信的实际应用. 实验一:发信实验,让开发板通过串口向电脑发送信息: #include <stdio.h> #include <stm32f10x.h> # ...
- Vi/Vim查找,替换,统计使用方法
Vi/Vim查找替换使用方法 vi/vim 中可以使用 :s 命令来替换字符串.该命令有很多种不同细节使用方法,可以实现复杂的功能,记录几种在此,方便以后查询. 可以使用 # 作为分隔符,此时中间出现 ...
- python爬虫 mac下安装使用Fiddler
HTTP代理工具Fiddler Fiddler是一款强大Web调试工具,它能记录所有客户端和服务器的HTTP请求. Getting started 在安装之前需要准备Mono环境 If you don ...
- 戏说 .NET GDI+系列学习教程(三、Graphics类的应用_验证码)
关于Graphics也有了基本了解下面想说的的是学这个东东干什么呢,到底如何应用目前常见应用1.验证码(参照网上的)2.打印排版(会提到关于条形码大小设置)3.自定义控件 一.验证码 class Va ...
- 剑指offer——47把数组排成最小的数
题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 题解: ...
- 常用内置模块(三)——shelve、xml、hashlib、configparser
常用模块(三) 一.shelve模块 1.shelve模块也是一种序列化模块,内部使用的是pickle模块,所以也存在跨平台性差的问题 2.特点: 只要提供一个文件名即可 读写的方式和字典一样 将数据 ...
- 高级UI晋升之View渲染机制(二)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android ...
- C# 反射入门
反射 别的用处先不管,至少在WinForm登录后的权限控制上有大用,比如登录后的窗体左侧树,点击通过字符串创建出窗体实例 案例如下图 AssTest类很简单 namespace assemblyTes ...
- Android网络(3):HttpClient作client,Tomcat Servlet作server的交互演示样例
前面相继介绍了Android网络编程里的Socket传输图片.HttpURLConnection,今天看HttpClient. 第一部分:JavaEE版的Eclipse配置Tomcat [备注:开发后 ...