概要
今天开始学习消息中间件,根据项目需求,目前选择的消息中间件是RabbitMQ。让我们一起来认识下RabbitMQ吧。
AMQP 的简介
在说RabbitMQ之前我们先简单的认识一下AMQP 协议,AMQP(Advanced Message Queuing Protocol) 直译为高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP 的主要特征是是面向对象,队列,路由(包括点对点的发布/订阅)、可靠性,安全。
RabbitMQ 的简介
RabbitMQ 是一个开源的AMQP 实现,服务器端用Erlang 语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。 同时其有消息确认机制和持久化机制,可靠性高。
RabbitMQ 组件概念
ConnectionFactory、Connection、Channel
Connection 是RabbitMQ的socket 链接,它封装了socket协议相关部分逻辑,ConnectionFactory是Connection的制造工厂,Channel 是我们 信息管道。我们的大部分业务操作都是在Channel 接口中完成,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
Broker
消息队列服务器的实体
Exchange
消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue
消息队列的载体,每个消息都会被投入到一个或多个队列。可以看成是一个有序的数组,
Binding
绑定,是一个操作,它的作用就是把exchange和queue按照路由规则绑定起来。RabbitMQ中通过绑定,以路由键作为桥梁将Exchange与Queue 关联起来(Exchange---->Routing Key---->Queue) ,这样RabbitMQ 就知道如何正确地将消息路由到指定的队列了,通过queueBind方法将Exchange、Routing Key 与Queue绑定起来。
Routing Key
路由关键字,exchange 根据这个关键字进行消息投递,Routing Key 需要与Exchange Type 及Binding Key 联合使用才能最终生效。 RabbitMQ为Routing Key设定的长度限制为255 bytes。
vhost
虚拟主机,一个broker 里可以开设多个vhost,用作不同用户的权限分离。
producer
消息生产者,就是投递消息的程序。
consumer
消息消费者,就是接受消息的程序
channel
消息通道,在客户端的每个连接里,可建立多个channel,每个channel 代表一个会话任务。
五种队列模式
简单队列
简单队列就是 生产者和消费者一对一
工作队列
工作队列就是一个生产者、2个消费者。但是在MQ中一个消息不能被两个消费者同时消费,要么被C1消费,要么被C2消费。这种模式类似于集群,能者多劳,性能好的可以安排多消费,性能低的可以安排低消费。
默认分发方式: 轮询分发
其他分发方式:公平分发
使用公平分发,必须关闭自动应答,改为手动应答。
消费者端添加代码:channel.basicQos(1);
----------------------------------完美的分割线------------------------------------
一般在实际应用场景中,我们基本上不会将消息直接投递到队列里,而是投递到Exchange(交换器,下图中的x)里, 由Exchange 将消息路由到一个或多个Queue 中。
发布订阅模式
这种模式可以满足消费者发布一个消息,多个消费者消费同一个消息的需求。广播给所有的接收者。
如上图所示,生产者(P)发送到Exchange(X)的所有消息都会路由到图中的两个Queue,并最终被两个消费者(C1与C2)消费。
1.一个生产者,多个消费者。通过交换器将消息投递到不同的队列里。
2.每个消费者都有自己的队列
3.生产者没有把消息发送到队列,而是发送到交换器Exchange里,Exchange 没有持久化功能,所以必须要与队列绑定
4。每个队列都绑定到交换器
5.生产者发送的消息经过交换器,路由到队列就能实现一个消息被多个消费者消费。
发布订阅模式代码讲解
伪代码—生产者
1.创建mq连接,通道
2.声明交换器–fanout 模式,把消息发送到交换器上(注意:交换器没有存储信息功能,不能持久化信息,因此,如果交换器没有绑定队列,那么消息就会丢失)
伪代码—消费者
3.创建mq连接,通道
4.声明队列
5.把队列绑定上交换器
6.消费者监听该队列的通道
路由器模式Routing
路由模式是在订阅模式基础上的完善,可以在生产消息的时候加入key 值,与key 值匹配的消费者消费信息。
以上图为例:我们以RoutingKey=“error” 发送消息到Exchange,则消息会路由到 Queue1(amqp.gen-S9b…,这是由RabbitMQ自动生成的Queue名称)和Queue2(amqp.gen-Agl…);如果我们以RoutingKey="info"或RoutingKey="warning"来发送消息,则消息只会路由到Queue2。如果我们以其他的RoutingKey来发送消息,则消息不会路由到这两个Queue中。
路由器模式代码讲解
伪代码–生产者
1.创建mq链接、通道
2.声明交换机–direct模式,把消息发送到交换机上,并指定routingKey,(注意:交换机没有存储信息功能,不能持久化消息,因此,如果交换机没有绑定队列,那么消息就丢失了)
伪代码–消费者
3.创建mq链接、通道
4。声明队列
5.把对列绑定到上交换机,并指定routingKey,多个就绑定多个routingKey
消费者监听该队列的通道
通配符模式–Topic 模式
通配符模式是在路由模式的升级,它允许key模糊匹配,* 代表一个或者多个词,通过通配符模式我们可以将C1对应的一个key准确定为item.add。而C2 我们就不需要一个个写出key值,而是用item.# 代替即可。
表示匹配一个。
表示匹配一个或多个。
如上图所示,我们以RoutingKey=“xx.orange.rabbit” 发送消息到Exchange,则消息会路由到Q1和Q2。RoutingKey=“lazy.orange.rabbit” 的消息会路由到Q1和Q2。RoutingKey="lazy.brown.fox"的消息会路由到Q2。RoutingKey=“lazy.pink.rabbit” 的消息会路由到Q2(只会投递给Q2一次,虽然这个RoutingKey与Q2的两个bindingKey 都匹配);routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息将会被丢弃,因为它们没有匹配任何bindingKey
通配符模式代码讲解
伪代码–生产者
1.创建mq链接、通道
2.声明交换机–topic模式,把消息发送到交换机上,并指定routingKey(注意:交换机没有存储信息功能,不能持久化消息,因此,如果交换机没有绑定队列,那么消息就丢失了)
伪代码–消费者
3.创建mq链接、通道
4.声明队列
5.把对列绑定到上交换机,并指定routingKey(可以用*和#来进行模糊匹配)
消费者监听该队列的通道
RPC 模式
MQ 本身是基于异步的消息处理,前面的示例中所有的生产者(P)将消息发送到RabbitMQ后不会知道消费者(C)处理成功或者失败。
在实际的应用场景中,我们很可能需要一些同步处理,需要同步等待服务端将我的消息处理完成后在进行下一步的处理,这相当于RPC(Remote Procedure Call, 远程过程调用)。在RabbitMQ中也支持RPC
参考
https://blog.csdn.net/u013256816/article/details/59117354
源代码
https://github.com/XWxiaowei/90-Java-demo-2/tree/master/course-24-rabbitmq/rabbitmq-demo