二、RabbitMQ基本概念
一、RabbitMQ基本概念
1.1 Broker
Broker:简单来说就是消息队列服务器实体
1.2 Producer
Producer: 消息生产者,就是投递消息的程序
1.3 Consumer
Consumer: 消息消费者,就是接受消息的程序
1.4 ConnectionFactory、Connection、Channel
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。
Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。
ConnectionFactory为Connection的制造工厂。
Channel: 消息通道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP连接。
Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
二、消息传递模型
我们都知道【生产者】将消息发送到 RabbitMQ 服务中,而【消费者】从其接受和使用消息。不过消息是如何在RabbitMQ中传递的呢?这里需要学习RabbitMQ的消息传递模型。
RabbitMQ 的消息传递模型的核心思想是,【生产者】不直接发送任何信息到队列。事实上,【生产者】根本就不知道消息是否会被传送到队列。
【生产者】只能发送消息到【消息交换机】。【消息交换机】一方面接收来自【生产者】的消息,另一方面是将接收到消息推送到队列中。
【消息交换机】必须知道它如何处理接收消息的确切方法。是发送到特定队列?发送到多个队列?或者它应该被丢弃?该规则由【消息交换机】的类型来定义。
2.1 消息交换机 Exchange
Exchange(交换器):用于接受、分配消息。
生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个或多个Queue中(或者丢弃)
核心概念:可以简化理解为路由器,其不存储数据,通常会和一个队列绑定,但也可以绑定到另一个交换器上。
其包括4种类型的交换器类型,生产实践中主要使用的类型是:可以精细管理的direct和topic两种。
1)direct,路由规则为完全匹配;
当消息中的RoutingKey(路由键)和交换器与队列之间的BindingKey(绑定键)完全匹配时,会发送消息给相应的队列
2)topic,支持完全匹配,也支持模糊匹配;
前面讲到direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。
topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,
匹配规则:
路由键一般:单词.单词.单词 构成.(单词为一个或者几个字母组成)
采用"*“和”#",用于做模糊匹配,其中"*“用于匹配一个单词,”#"用于匹配多个单词(0~n)个。
举例说明:
路由键:rrr.kkk.*可以匹配绑定键:rrr.kkk.lll。
路由键:xxx.# 可以匹配绑定键:xxx.mmm.kkk
3)fanout,把当前路由器下所有消息发送到与该交换器绑定的队列中(不在意绑定键的有无与匹配);
4)header,实际中无应用。
headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers 属性进行匹配。
在绑定队列和交换器时制定一组键值对,当发送消息到交换器时,RabbitMQ 会获取到该消息的headers (也是一个键值对的形式),对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果完全匹配则消息会路由到该队列,否则不会路由到该队列。(注:该交换器类型性能较差且不实用,因此一般不会用到)。
2.2 队列 Queue
Queue: 消息队列,是RabbitMQ的内部对象,用来保存消息直到发送给消费者。
- 它是消息的容器,也是消息的终点。
- 一个消息可投入一个或多个队列。
- 消息一直在队列里面,等待消费者连接到这个队列将其取走。
- 多个消费者可以订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
2.3 绑定键 BindingKey
绑定键是用于绑定【消息交换机】和【队列】的一个字符串。
当【消息交换机】接受到消息后,会检查消息附带的【路由键】;如果【路由键】和某个【绑定键】匹配,则【消息交换机】会将此消息,分配到对应的【队列】中。
在绑定多个Queue到同一个Exchange的时候,这些Binding允许使用相同的binding key。
bindingKey 并不是在所有情况下都生效,它依赖于Exchange Type,比如fanout类型的Exchange就会无视bindinKey,而是将消息路由到所有绑定到该Exchange的Queue。
2.4 路由键 RoutingKey
在【生产者】向 RabbitMQ 发送消息时,一般会附带一个称为【路由健】的字符串。
【消息交换机】会根据这个字符串,来匹配【消息交换机】自身设置的【绑定键】;当【路由健】和【绑定键】匹配后,就可以确定此消息会进入的【队列】了。
三、RPC(Remote Procedure Call,远程过程调用)
MQ本身是基于异步的消息处理,所有的生产者(P)将消息发送到RabbitMQ后不会知道消费者(C)处理成功或者失败(甚至连有没有消费者来处理这条消息都不知道)。
但实际的应用场景中,我们很可能需要一些同步处理,需要同步等待服务端将我的消息处理完成后再进行下一步处理。这相当于RPC(Remote Procedure Call,远程过程调用)。在RabbitMQ中也支持RPC。
RabbitMQ中实现RPC的机制是:
客户端发送请求(消息)时,在消息的属性(MessageProperties,在AMQP协议中定义了14种properties,这些属性会随着消息一起发送)中设置两个值:
replyTo:一个Queue名称,用于告诉服务器处理完成后将通知我的消息发送到这个Queue中;
correlationId:此次请求的标识号,服务器处理完成后需要将此属性返还,客户端将根据这个id了解哪条请求被成功执行了或执行失败。
服务器端收到消息并处理;
服务器端处理完消息后,将生成一条应答消息到replyTo指定的Queue,同时带上correlationId属性;
客户端之前已订阅replyTo指定的Queue,从中收到服务器的应答消息后,根据其中的correlationId属性分析哪条请求被执行了,根据执行结果进行后续业务处理。
三、传递模型:
1、点多点模型PTP
每个消息只用一个消费者;
发送者和接收者没有时间依赖;
接受者确认消息接受和处理成功;
2、发布-订阅模型Pub/Sub
一对多关系,通过订阅主题,发布者建立一个订阅,订阅者保持持续的活动状态以接收消息。
每个消息可以有多个订阅者
客户端只有订阅后才能接收到消息,有时间依赖。
持久订阅 订阅关系建立后,消息不会消失,不管订阅者是否都在线
非持久订阅 订阅者为了接受消息,必须一直在线
四、典型的应用案例
1、注册时发送邮件或发送短信
2、日志分析使用,多个服务产生的数据发送到中间件发送到分析服务。
3、消息复制,用于跨机房数据传输、搜索、离线数据计算等。
4、延迟消息发送和暂存,把中间件当成可靠的消息暂存地。接受消息,暂时先不发送。