RabbitMQ学习目标
提示:这里可以添加学习目标
- 了解消息中间件的使用场景、发展、背景知识等
- 掌握RabbitMQ消息中间件的构架、模型和使用(开发、运维、集群部署、监控等)
- 掌握消息可靠性、幂等性、顺序消息、延迟消息、事务消息等进阶知识,以及大规模生产环境的使用经验。
- 理解背后构架设计思想以及在高性能存储系统、网络编程技巧。
- 理解消息中间件的优缺点
学习内容:
1、 RabbotMQ构架与实战
2、 RabbitMQ高级特性解析
3、RabbitMQ集群与运维
4、 RabbitMQ源码剖析
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、RabbitMQ介绍、概念、基本架构
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
1.RabbitMQ介绍
- 高可靠性、易扩展、高可用、功能丰富等
- 支持大多数(甚至冷门)的编程语言客户端。
- RabbitMQ遵循AMQP协议,自身采用Erlang(一种由爱立信开发的通用面向并发编程的语言)编写。
- RabbitMQ也支持MQTT等其他协议
2.RabbitMQ整体逻辑构架
2.1 RabbitMQ Exchange类型
RabbitMQ常用的交换器类型有: fanout 、 direct 、 topic 、 headers 四种。
(1)fanout
会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中
(2)direct
direct类型的交换器路由规则很简单,它会把消息路由到那些BindingKey和RoutingKey完全匹配的队列中,如下图:
(3)topic
topic类型的交换器在direct匹配规则上进行了扩展,也是将消息路由到BindingKey和RoutingKey相匹配的队列中,这里的匹配规则稍微不同,它约定:
BindingKey和RoutingKey一样都是由"."分隔的字符串;BindingKey中可以存在两种特殊字符“”和“#”,用于模糊匹配,其中"“用于匹配一个单词,”#"用于匹配多个单词(可以是0个)。
(4)headers
headers类型的交换器不依赖于路由键的匹配规则来路由信息,而是根据发送的消息内容中的headers属性进行匹配。在绑定队列和交换器时指定一组键值对,当发送的消息到交换器时,RabbitMQ会获取到该消息的headers,对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果匹配,消息就会路由到该队列。headers类型的交换器性能很差,不实用。
3.RabbitMQ数据存储
3.1存储机制
(1)RabbitMQ消息两种类型
- 持久化消息和非持久化消息。
- 这两种消息都会被写入磁盘。
持久化消息会保存到磁盘,并且保存一部分到内存。当内存吃紧时才会释放一部分内存提高性能。非持久化会保存在内存当中,当内存不够时会保存到到磁盘,节省空间。
(2)RabbitMQ存储层包含两部分:队列索引和消息存储
二、RabbitMQ工作流程
1.生产者发送消息的流程
- 生产者连接RabbitMQ,建立TCP连接( Connection),开启信道(Channel)
- 生产者声明一个Exchange(交换器),并设置相关属性,比如交换器类型、是否持久化等
- 生产者声明一个队列井设置相关属性,比如是否排他、是否持久化、是否自动删除等
- 生产者通过 bindingKey (绑定Key)将交换器和队列绑定( binding )起来
- 生产者发送消息至RabbitMQ Broker,其中包含 routingKey (路由键)、交换器等信息
- 相应的交换器根据接收到的 routingKey 查找相匹配的队列。
- 如果找到,则将从生产者发送过来的消息存入相应的队列中。
- 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者
- 关闭信道。
- 关闭连接。
2.消费者接收消息的过程
- 消费者连接到RabbitMQ Broker ,建立一个连接(Connection ) ,开启一个信道(Channel) 。
- 消费者向RabbitMQ Broker 请求消费相应队列中的消息,可能会设置相应的回调函数, 以及
做一些准备工作 - 等待RabbitMQ Broker 回应并投递相应队列中的消息, 消费者接收消息。
- 消费者确认( ack) 接收到的消息。
- RabbitMQ 从队列中删除相应己经被确认的消息。
- 关闭信道。
- 关闭连接
3.案例
Hello World一对一的简单模式。生产者直接发送消息给RabbitMQ,另一端消费。未定义和指定Exchange的情况下,使用的是AMQP default这个内置的Exchange。
4.Connection和Channel
生产者和消费者需要与RabbitMQ建立TCP连接,也就是Connection。TCP连接建立起来的时候客户端会被建立一个信道(channel),每个信道一个ID。
为什么不直接使用TCP连接而是建立信道?
- 复用TCP协议减少开销
- 每个信道流量不是很大时候复用单一的connection可以减少TCP连接资源
- 当流量很大时,一个connection就会产生瓶颈流量被限制。需要建立多个connection,分摊信道。
5.RabbitMQ工作模式详解
5.1work Queue
生产者发消息,启动多个消费者实例来消费消息,每个消费者仅消费部分信息,可达到负载均衡的效果。
5.2发布订阅模式
- 每个消费者定义生成一个队列并绑定到同一个Exchange,每个消费者都可以消费到完整的消息。
- 消费广播给所有订阅该消息的消费者
- 生产者将消息发给交换器。交换器从生产者接受到消息,将消息推给消息队列。交换器必须清楚的知道怎么处理接收到的消息应该追加到指定的一个队列还是多个队列、还是丢弃。
- 发布订阅模式使用的交换器是fanout交换器。
(1)临时队列
连接RabbitMQ的时候需要一个新的,空的队列。其次断开消费者的连接,该队列应该自动删除。
String queueName = channel.queueDeclare().getQueue();
这样声明了一个非持久化、排他的、自动删除的队列,并且名字是服务器随机生成的。queueName一般的格式类型:
amq.gen-JzTY20BRgKO-HjmUJj0wLg 。
(2)绑定队列
在创建队列和fanout交换器之后,我们需要将两者进行绑定,让交换器将消息发送该队列。
channel.queueBind(queueName, "logs", "");
这时交换器会接受到消息追加到我们的队列中,并且使用下面命令列出绑定关系:
rabbitmqctl list_bindings
5.3 路由模式
使用 direct 类型的Exchange,发N条消费并使用不同的 routingKey ,消费者定义队列并将队列、 routingKey 、Exchange绑定。此时使用 direct 模式Exchagne必须要 routingKey 完全匹配的情况下消息才会转发到对应的队列中被消费。路由模式就可以让接受者接收部分信息。
(1)绑定队列
上一模式中,交换器的使用方式:
channel.queueBind(queueName, EXCHANGE_NAME, "");
绑定语句还有第三个参数:routingKey
channel.queueBind(queueName, EXCHANGE_NAME, "black");
bindingKey 的作用与具体使用的交换器类型有关。对于 fanout 类型的交换器,此参数设置无效,系统直接忽略。
5.4 direct交换器
使用direct交换器可以对日志进行不同处理:只需要将消息的rountingkey和队列的bingingkey相对应,消息就可以推送给队列。
上图中的交换器 X 是 direct 类型的交换器,绑定的两个队列中,一个队列的 bindingKey 是orange ,另一个队列的 bindingKey 是 black 和 green 。如此,则 routingKey 是 orange 的消息发送给队列Q1, routingKey 是 black 和 green 的消息发
送给Q2队列,其他消息丢弃。
(1)多重绑定队列
上图中,我们使用 direct 类型的交换器 X ,建立了两个绑定:队列Q1根据 bindingKey 的值black 绑定到交换器 X ,队列Q2根据 bindingKey 的值 black 绑定到交换器 X ;
交换器 X 会将消息发送给队列Q1和队列Q2。交换器的行为跟 fanout 的行为类似,也是广播。
5.5 主题模式
topic类型的交换器背后原理和direct类型的类似,只要队列的bingingKey的值与消息的routingKey匹配,队列就可以收到该消息。有两个不同点:
- *(star)匹配一个单词
- #匹配0到多个单词
总结
提示:接下来将继续介绍其高级特性