大家好,我是 tc,今天为大家介绍一下RabbitMQ中的4种exchange,水平一般,能力有限,若有错误之处,欢迎指正。
对RabbitMQ稍有了解的朋友应该都知道,在RabbitMQ中,一个有4中Exchange,分别是direct、topic、fanout、headers。
其实,还有一个默认的交换机,称为default exchange,其本质也是一个direct exchange。在这4种exchange中,最常用的是direct、topic、fanout。
下面,我们就通过代码示例分别介绍这4种exchange的用法,以及应用场景。
本文中代码涉及到的RabbitMQ的配置如下。
本文中代码涉及到的MAVEN依赖如下。
direct exchange
此种类型的交换机是通过routing key 和队列绑定在一起的。
通过一个routing key,交换机可以绑定一个队列,也可以同时绑定多个队列。
如果一个交换机绑定了多个队列,则交换机会将消息分别路由给每一个队列,也就是说每个队列都会得到一份全量的消息。
例如,交换机绑定了2个队列,接到生产者的10条消息后,不是分别向两个队列发送5条消息,而是向2个队列都发送10条消息。
下面,我们通过代码简单演示一下direct exchange的使用方式。
交换机绑定一个队列
启动类RabbitmqDemoApplication代码如下
@EnableRabbit注解的作用是开启基于注解的RabbitMQ。
生产者Producer代码如下
convertAndSend方法的作用就是向RabbitMQ发送消息,第一个参数"directExchange"指交换机的名称,
第二个参数"rk.001"指routing key,第三个参数是消息。
消费者代码如下
@RabbitListener注解的作用是指定目标方法来作为消费消息的方法,通过参数queues指定监听的队列,通过参数bindings指定监听的绑定。
其中,@Queue("queue.test.001") 在项目启动时,会创建一个名为queue.test.001的队列。
@Exchange("directExchange") 在项目启动时,会创建一个名为directExchange的交换机,如果不指定类型,默认就是direct exchange。
key指定交换机和队列的绑定的routing key。
通过如此配置,交换机directExchange就通过routing key“rk.001”和队列queue.test.001绑定在一起了。
一旦生产者向交换机directExchange发送消息,并指定routing key为“rk.001”,消费者consumer就可以消费消息了。
单元测试代码如下
测试结果如下
从测试结果来看,消费者正常消费了10条消息,与我们上面的预测是一致的。
RabbitMQ控制台如下
队列信息如下图。
交换机信息如下图。
交换机绑定多个队列
除了消费者代码之外,其他代码和上面相同,就不在赘述。
消费者代码如下
如上图代码所示。
我们创建了两个队列queue.test.001和queue.test.002,并都将其通过相同的routing key “rk.001”绑定到同一个交换机directExchange上。
按照我们上面的推测,这两个消费者process1和process2,都会消费10条消息。
测试结果如下
如上图所示,测试结果证明了我们的推测是正确的。
RabbitMQ控制台如下
队列信息如下。
交换机信息如下。
适用场景
1、适用于业务数据需要直接传输并消费的场景,比如不同业务模块之间的消息交互,就可以借助基于DirectExchange的消息模型进行通信。
2、点对点聊天
topic exchange
和direct exchange类似,topic exchange也是根据routing key,将exchange和queue绑定在一起。
区别在于,direct exchange的routing key 是精确匹配,而topic exchange的的routing key 是模式匹配,类似于正则表达式匹配。
routing key 可以是类似 *.orange.* 或者 lazy.# 的表达式。其中,* (星) 代表一个单词,# (hash) 代表0个或多个单词。
从上面的运行示意图中,我们可以看出queues中绑定的routing key是模糊的,usa.#这个routing key可以接收到usa.news和usa.weather的消息;而#.news这个routing key可以接收到usa.news和europe.news的消息。
下面,我们通过一个代码示例简单介绍一下topic exchange的用法,以及应用场景。
示例代码
生产者代码
如上图所示,我们创建了四个生产者,向topicExchange交换分别发送一条消息,同时指定routing key。
消费者代码
如上图所示,我们创建了四个消费者,并创建一个topic exchange,创建4个队列,并分别指定routing key,其中,*表示一个单词。
单元测试代码
测试结果
从上图可以看出:
消费者一通过routing key(usa.*)消费了两条和usa相关的消息,分别是生产者一和生产者二发送的消息;
消费者二通过routing key(*.news)消费了两条和news相关的消息,分别是生产者一和生产者三发送的消息;
消费者三通过routing key(europe.*)消费了两条和europe相关的消息,分别是生产者三和生产者四发送的消息;
消费者四通过routing key(*.weather)消费了两条和weather相关的消息,分别是生产者二和生产者四发送的消息;
和我们上面的推测是一致的。
RabbitMQ控制台信息
队列信息如下,可以看出我们创建了4个队列。
交换机信息如下,可以看出我们创建了一个topic类型的交换机。
适用场景
1、涉及分类或标记的新闻更新,例如体育新闻、娱乐新闻、社会新闻、金融新闻等分类推送。
2、后台任务处理,每个工作线程处理特定的任务。
fanout exchange
和direct exchange、topic exchange不同,fanout exchange不使用routing key,它会将消息路由到所有与其绑定的队列。
fanout exchange是消息广播路由的理想选择。
和direct exchange的一个交换机绑定多个队列的情况一样,绑定了fanout exchange的队列,都会接收到一份全量的消息。
示例代码
生产者代码
我们创建了4个生产者,指定交换机为fanoutExchange,但是没有指定routing key。
消费者代码
如上图,我们创建了4个消费者,同样指定交换机是fanoutExchange,且类型是fanout,同时还指定了routing key。
单元测试代码
测试结果
从上图的测试结果中可以看出,绑定了fanout exchange的每一个队列,都全量消费了消息。
我们在发送消息时,只指定了交换机,没有指定routing key,在消费者这边也指定了交换机,同时还指定了routing key,结果每个绑定了交换机的队列都可以消费到全量消息,这说明了fanout exchange不使用routing key,它会将消息路由到所有与其绑定的队列。
RabbitMQ控制台信息
队列信息如下。
交换机信息如下。
适用场景
1、适用于广播消息的场景
2、群聊功能,广播消息给当前群聊中的所有人
3、大型多人在线游戏的游戏积分排行榜更新
4、体育新闻客户端实时更新分数
5、分布式系统可以广播各种状态和配置更新
headers exchange
和上面三种交换机类型不同,headers exchange是根据Message的一些头部信息来分发过滤Message的,它会忽略routing key的属性,如果Header信息和message消息的头信息相匹配,那么这条消息就匹配上了。
有一个重要参数x-match:当“x-match”参数设置为“any”时,只要一个匹配的header 属性值就足够了;当“x-match”设置为“all”时,意味着所有值都必须匹配,才能将交换机和队列绑定上。
示例代码
配置代码
如上图所示,我们配置了三个队列:queue.headers.001、queue.headers.002和queue.headers.003,并创建了一个Headers类型的交换机headerExchange。
将队列queue.headers.001绑定到headerExchange上,并指定x-match=any,绑定的属性分别是type = 1,name = send11,也就是说,只能有一个属性可以匹配上,消费者就可以消费消息。
将队列queue.headers.002绑定到headerExchange上,并指定x-match=all,绑定的属性分别是type = 2,name = send2,也就是说,必须两个属性都匹配上,消费者才可以消费消息。
将队列queue.headers.003绑定到headerExchange上,并指定x-match=all,绑定的属性分别是type = 3,name = send33,也就是说,必须两个属性都匹配上,消费者才可以消费消息。
生产者代码
如上图所示,我们配置了三个生产者。
生产者一向交换机headerExchange发送消息,同时指定了两个headers属性:type = 1,name = send1;
生产者二向交换机headerExchange发送消息,同时指定了两个headers属性:type = 2,name = send2;
生产者三向交换机headerExchange发送消息,同时指定了两个headers属性:type = 3,name = send3;
消费者代码
如上图所示,我们配置了三个消费者,分别消费队列queue.headers.001、queue.headers.002和queue.headers.003的消息。
我们在上面的配置文件中,将queue.headers.001和headerExchange绑定在一起了,且只要有一个headers属性匹配上就可以消费消息;
将queue.headers.002、queue.headers.003也和headerExchange绑定在一起了,且必须所有的headers属性都匹配上才可以消费消息;
从上面的代码中,我们可以作出如下推测:
1、消费者一可以正常消费消息。因为生产者一发送消息时指定了type = 1,name = send1属性,而在配置文件中,同样配置了type = 1,name = send11属性,且x-match = any,正好有一个type = 1 属性是可以匹配上的,故而可以可以正常消费消息。
2、消费者二可以正常消费消息。因为生产者二发送消息时指定了type = 2,name = send2属性,而在配置文件中,同样配置了type = 2,name = send2属性,且x-match = all,两个headers属性都可以匹配上,故而可以正常消费消息。
3、消费者三不可以正常消费消息。因为生产者三发送消息时指定了type = 3,name = send3属性,而在配置文件中,同样配置了type = 3,name = send33属性,且x-match = all,两个headers属性只有type可以匹配上,故而不可以正常消费消息。
单元测试代码
测试结果
从上图可以看出,消费者一和消费者二可以正常消费消息,但是消费者三没有消费,因为没有匹配上。
RabbitMQ控制台信息
队列信息如下。
交换机信息如下。
适用场景
1、适用于routing key非常复杂或者灵活多变的场景
标签:绑定,系列,Exchange,队列,exchange,RabbitMQ,交换机,routing,key From: https://www.cnblogs.com/tiancai/p/18470464