简介

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 基础入门的更多相关文章

  1. spring boot 中 rabbit mq基础例子

    1.先安装ELANG,再按照RabbitMQ 2.打开RabbitMQ控制台:rabbit command prompt 1.设置elang的路径:set ERLANG_HOME=D:\work_pr ...

  2. rabbit mq 基础流程(转)

    从AMQP协议可以看出,MessageQueue.Exchange和Binding构成了AMQP协议的核心,下面我们就围绕这三个主要组件    从应用使用的角度全面的介绍如何利用Rabbit MQ构建 ...

  3. Rabbit MQ 入门指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  4. ASP.NET Core消息队列RabbitMQ基础入门实战演练

    一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...

  5. rabbitmq(一)-基础入门

    原文地址:https://www.jianshu.com/p/e186a7fce8cc 在学东西之前,我们先有一个方法论,知道如何学习.学习一个东西一般都遵循以下几个环节: xxx是什么,诞生的原因, ...

  6. 在 Windows 上安装Rabbit MQ 指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  7. (转)在 Windows 上安装Rabbit MQ 指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  8. celery rabbit mq 详解

    Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, ...

  9. Rabbit MQ 消息确认和持久化机制

    一:确认种类 RabbitMQ的消息确认有两种.一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递.发送确认分为两步,一是确认是否到达交换器,二是确认是否到 ...

随机推荐

  1. RF中滚动条的操作方法小结

    滚动条分为俩种,一:主页面中的滚动条.二:页面中的子页面的滚动条. 每种滚动条有都分为上下滑动与左右滑动. 下面分别介绍: 一:主页面的滚动条上下滑动: execute javascript      ...

  2. CSS:CSS 伪类(Pseudo-classes)

    ylbtech-CSS:CSS 伪类(Pseudo-classes) 1.返回顶部 1. CSS 伪类(Pseudo-classes) CSS伪类是用来添加一些选择器的特殊效果. 语法 伪类的语法: ...

  3. JWT(JSON Web Token) 多网站的单点登录,放弃session 转载https://www.cnblogs.com/lexiaofei/p/7409846.html

    多个网站之间的登录信息共享, 一种解决方案是基于cookie - session的登录认证方式,这种方式跨域比较复杂. 另一种替代方案是采用基于算法的认证方式, JWT(json web token) ...

  4. PAT_A1075#PAT Judge

    Source: PAT A1075 PAT Judge (25 分) Description: The ranklist of PAT is generated from the status lis ...

  5. C++ 操作json文件

    一.环境搭建: 参考文章:https://blog.csdn.net/fakine/article/details/79272090 二.创建实例: #include <stdio.h> ...

  6. linux每日命令(2):ps命令

    ps命令真是我比较常用的命令了,只是也没咋仔细研究过,最大的用处就是写代码的时候,起了多进程,就会占用多个进程,如果程序异常了,进程确没有kill掉,那么再启动程序就会报错 正常起项目 如果进程被占用 ...

  7. Java中++操作是同步的吗?为什么?

    不是同步的 因为++操作分为三步实现 内存到寄存器 寄存器自增操作 寄存器写回内存 这三步每一步都可以被打断,不是原子操作,所以不是同步操作

  8. 提供免费可商用的优秀背景视频素材——COVERR

    现在经常看到很多网站都是贴近更现代化的设计,首页都会放置跟网站内容相关的视频短片作为背景,不用按下播放按钮,就有动态显示效果,跟以往静态图片相较下更动态.更有活力,对网站的视觉体验有一定的提升作用.但 ...

  9. css3 一个六边形 和 放大旋转动画DEMO演示

    <!DOCTYPE html> <html> <head> <meta charset="gb2312"> <title> ...

  10. tomcat nio apr

    NIO[root@localhost ~]# vim /usr/local/tomcat9/conf/server.xml<Connector port="8080" pro ...