这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
RabbitMQ核心组成部分
在了解RabbitMQ的四种交换机之前,我们需要先了解一下RabbitMQ的核心组成部分及其相关的核心概念。
核心概念
Server:又称Broker,是消息中间件服务的节点,接收客户的连接、实现AMQP实体服务。
Connection:连接、应用程序与Broker的网络连接,TCP/IP三次握手四次挥手,一个连接中包含成百上千个Channel
Channel:信道,几乎所有的操作都是在Channel中进行的,Channel提供消息读写的通道,每个Channel代表一个会话任务。信道是建立在TCP连接上的虚拟连接,rabbitmq在一条TCP上建立多个信道来达到多个线程处理,这一条TCP由多个线程共享,每一个线程对应TCP上的一个Channel,它们彼此之间互不影响。
Message:消息,服务与应用程序之间传送的数据。由Properties和Body组成,Properties可以对消息进行修饰,比如消息的优先级、延迟等高级特性,Body是消息的内容。
Virtual Host:虚拟消息服务器,每个Virtual Host相当于一个相对独立的RabbitMQ服务器;每个Virtual Host之间是相互隔离的,exchange、queue、message不能互通。可以将RabbitMQ理解为一个数据库,而Virtual Host就是其中的一个库。
Exchange:交换机,接收消息,根据路由key发送消息到该路由key绑定的消息队列(不具备消息存储的能力),负责投递消息给队列,如果没有 Queue bind 到 Exchange 的话,它会直接丢弃掉 Producer 发送过来的消息。常用的交换机类型有:direct、fanout、topic、headers
Binding:Exchange交换机和Queue队列之间的虚拟连接。binding中可以保护多个路由key
Routing key:路由键是一个路由规则,虚拟机会根据路由键路将一个消息从交换机路由到一个绑定的队列。
Queue :队列,保存消息,消费者可以从队列中获取消息。
RabbitMQ四种类型交换机
direct(routing key)
处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配,这是一个完整的匹配,所谓完整匹配,是指路由键需要一模一样。如果一个队列绑定到该交换机上binding key为 “sms”
,则只有发送消息时指定routing key为“sms”
的消息才被转发到该队列,不会转发到eamil,也不会转发到sms.abc,只会转发sms。因此,当使用特定 routing key 发送的消息将被传递到与匹配binding key绑定的所有队列。同时,RabbitMQ允许一个队列通过多个binding key与一个交换机进行绑定,在交换机进行消息投递的时候,只要生产者指定的routing key满足其中一个binding key即可将消息路由到指定的队列。如下图,只要生产者发送消息指定routing key为sms
或者test
,消息都能被投递到Queue2队列。(这里出现的bingding key
其实也叫 routing key,只是为了与发送消息时指定的routing key区分开来,避免混淆)
Web端测试direct类型交换机
- 首先增加一个direct模式的交换机,名称为
direct-exchange
- 新建队列queue1、queue2并将其绑定到名称为
direct-exchange
交换机上,并为每个队列指定binging key(注意:这里的绑定即可以在交换机端绑定队列,也可以在队列端将队列绑定到交换机上)。
- queue1
- queue2
- 绑定后的交换机如下:
- 交换机投送消息到队列时指定routing key,根据routing key将消息投递到指定的队列(这里Web端直接在交换机中指定binging key,在实际生产中是在生产者端发消息时进行指定)
- 很明显,消息的确被投递到了queue1,因为queue1与
direct-exchange
绑定时指定bingding key为sms
,而发送消息指定的routing key也为“sms”
,因此消息会发送到queue1中.
- 从队列queue1中获取消息
fanout类型交换机
不处理路由键。只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout交换机转发消息是最快的。
Web端测试fanout类型交换机
- 新建一个fanout类型的交换机
- 将上面将的两个队列queue1、queue2绑定到fanout类型的交换机上,只是这次无需指定bindinging key。
- queue1
- queue2
- 完成队列绑定后的交换机如下
- fanout交换机发送消息,无需指定routing key,到底哪个队列会收到呢?
- 很明显,两个与fanout-exchange交换机绑定的queue1和queue2都收到了交换机投递的消息,这就是fanout类型的交换机,会将消息以广播的方式投递到与之绑定的所有队列上。
topic(模糊匹配的routing key)
topic交换机可以实现更加复杂的消息发送规则,即发送消息时,指定更为复杂的routing key,类似于模糊匹配,routing key可以多变。只要发送消息时指定的routing key符合交换机与队列绑定的binding key的匹配规则,则消息可以被正确投递到指定队列。
-
模糊匹配符号及其规则
#
:代表匹配一个多或多个、或者一个也匹配不到,支持多级*
:代表必须匹配一个,且只能是一级,即如果binding key为*.sms.*
,则只有发送消息时指定routing key为类似a.sms.b
等的消息才会被投递到该队列,如果routing key 为sms.b
或者a.sms
或者a.b.sms
,则都不会被投递到该队列。
Web端测试topic类型交换机
- 新建一个topic类型的交换机,名称为
topic-exchange
- 将之前的queue1和queue2绑定到topic-exchange交换机上,与绑定direct类型的交换机不同的是,这次的binding key采用的是模糊匹配。
- queue1,指定binding key为
*.sms.*
- queue2,指定binding key为
#.email
- 绑定完队列的topic类型的交换机
- 首先,topic类型的交换机发送一条消息(此时有两个队列与该交换机绑定),指定routing key为
a.sms.b
,消息会被投递到哪个队列呢,还是一个都不投递?
- 没错,只有队列queue1接收到消息,因为我们指定的
routing key = a.sms.b
,与binding key=*.sms.*
匹配,因此消息能够被正确投递。如下图:
接着,我门发送两条消息,分别指定两条消息的routing key为 email
和a.b.email
- 第一条消息
- 第二条消息
- 很明显,两次的消息都成功发送到了queue2,且不会被投递到其他队列,因为两次消息指定的routing key都与队列queue2和交换机绑定的binding key相匹配,因此可以被正确匹配。
headers类型交换机
headers交换机和topic交换机有点相似,但是topic交换机的路由是基于路由键,而headers交换机的路由则是基于消息的headers数据,所以在发送消息给headers类型的交换机时指定routing key是没有任何效果的。headers类型的交换机在绑定队列时需要指定参数Arguments,发送消息时需要指定headers和Arguments相匹配,消息才能被投递到对应的队列中。
Web端测试headers类型交换机
-
新建一个headers类型的交换机,名称为headers-exchange
-
将之前的队列queue1和queue2绑定到headers-exchange交换机上,无需指定binding key,但是需要指定Arguments参数。
- queue1,指定Arguments为
x = 1
- queue2,指定Arguments为
y = 1
- 完成队列绑定后的headers交换机
- header类型的交换机发送消息,指定headers为
x=1
- 很明显,消息被投递到了queue1,因为发送消息时指定的headers和队列queue1与交换机绑定的Arguments相匹配,因此消息可以被正确投递到queue1。
- 接下来,我们测试发送消息时指定多个headers,看看消息会被发送到哪些队列,指定两个headers分别为
x=1
和y=1
- 从以下可以看出,消息被同时投递到了queue1和queue2这两个队列,因为两个headers都与queue1和queue2绑定交换机时定义的Arguments相匹配,则消息能够被路由到这两个队列。
- 同理,如果你投递消息时指定的headers与绑定的参数Arguments都不匹配,则会提示消息无法路由到与之绑定的任何队列。如果只有一个headers匹配到Arguments,则只有该匹配到的队列能够接收到消息。
总结
direct类型的交换机是一种需要处理routing key的交换机,发送消息时需要指定routing key,会将消息根据routing key路由到指定的队列。fanout是一种无需处理路由键的交换机,消息会被发送到与交换机绑定的所有队列中,即广播模式。topic交换机会根据一定的规则,根据 routing key 把消息投递到符合规则的队列中,是一种比direct更加灵活的路由方式。headers类型的交换机是根据消息的headers来投递消息而不是根据 routing key 来投递消息,在绑定队列时需要指定参数Arguments,发送消息时只有指定的headers与队列绑定时对应的Arguments相匹配时,消息才会被正确投递。
🏁以上就是对RabbitMQ四种交换机类型介绍,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍