rabbitmq中交换机类型direct和topic的区别
rabbitmq主要有三大类交换机:fanout,direct,topic,他们从名字上分别是扇区交换机、直连交换机和主题交换机。其实还有headers一类的交换机,这里不去深究。
fanout交换机也叫无路由交换机,就是它直接与交换机exchange发生关联,不用routingKey。
direct和topic都加入了routingKey的概念,发送数据的时候,它只跟交换机和路由发生关系,不关心最终的队列queue。就是生产者这里只需要将消息绑定到exchange和routingKey上,如果是springboot与rabbitmq关联,我们可以从api上来看看:
@Override
public void convertAndSend(String exchange, String routingKey, final Object object) throws AmqpException {convertAndSend(exchange, routingKey, object, (CorrelationData) null);
}
这是一个很直观的方法,方法体中跟rabbitmq有关的只是exchange,routingKey,object。
这里也引出了本文的主要内容:direct类型和topic类型到底有什么区别呢?区别就是:direct类型从字面上看就是直连的意思,从生产者到消费者这条线上,routingKey只能一一对应,而topic主题类型生产者到消费者routingKey可以多对一。可以用如下直观的图形表示:
如果这段描述还不是很清晰,请看下面一个示例:
springboot整合rabbitmq
maven依赖:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.4.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!-- tool --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.58</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
rabbitmq连接配置信息:
spring:rabbitmq:addresses: 192.168.226.100:5672username: hualipassword: hualivirtual-host: /mecpublisher-confirms: trueconnectionTimeout: 5000template:madatory: truelistener:simple:acknowledge-mode: manualconcurrency: 1max-concurrency: 10retry:enabled: true
RabbitTemplate配置
package com.huali.mec.parse.config;import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AMQPConfig {@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate template = new RabbitTemplate(connectionFactory);return template;}
}
监听器,这里是消费者:
package com.huali.mec.parse.listener;
import java.io.IOException;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;@Component
public class UpMessageListener {@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "queue1",durable = "true"), exchange = @Exchange(value="MEC1",type = ExchangeTypes.TOPIC),key = "test.#")})public void topicHandler(Message message,Channel channel) throws IOException{System.out.println("receive topic message -> "+new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "queue2",durable = "true"), exchange = @Exchange(value="MEC2",type = ExchangeTypes.DIRECT),key = "test.aaa")})public void directHandler(Message message,Channel channel) throws IOException{System.out.println("receive direct message -> "+new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}/*@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "queue2",durable = "true"), exchange = @Exchange(value="MEC2",type = ExchangeTypes.DIRECT),key = "test.bbb")})public void directHandler2(Message message,Channel channel) throws IOException{System.out.println("receive direct message -> "+new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}*/}
这里是生产者,注释的部分是用来发送direct类型消息的,这样可以看清楚他们的区别。
package com.huali.mec.parse.service;import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class PublishService {@Autowiredprivate RabbitTemplate rabbitTemplate;public void send(String msg) {rabbitTemplate.convertAndSend("MEC1", "test.aaa", msg);rabbitTemplate.convertAndSend("MEC1", "test.bbb", msg);//rabbitTemplate.convertAndSend("MEC2", "test.aaa", msg);//rabbitTemplate.convertAndSend("MEC2", "test.bbb", msg);}
}
启动类,启动的时候循环发送10次消息。
package com.huali.mec.parse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.huali.mec.parse.service.PublishService;@SpringBootApplication
public class ParseApp implements CommandLineRunner{public static void main( String[] args ){SpringApplication.run(ParseApp.class, args);}@Autowiredprivate PublishService publishService;@Overridepublic void run(String... args) throws Exception {for(int i=0;i<10;i++) {publishService.send("hello,"+i);}}}
运行这段示例,只需要准备好一个rabbitmq服务器,设定好本文所需vhost即可。队列和交换机都不用创建并绑定,程序启动会自动创建并绑定路由关系。
这里运行分三步:
1、直接运行本示例代码,可以查看topic交换机的输出:控制台打印20次消息,因为消费者绑定了routingKey是test.#就是会消费来自test.aaa和test.bbb的所有消息。
receive topic message -> hello,0
receive topic message -> hello,0
receive topic message -> hello,1
receive topic message -> hello,1
receive topic message -> hello,2
receive topic message -> hello,2
receive topic message -> hello,4
receive topic message -> hello,3
receive topic message -> hello,3
receive topic message -> hello,4
receive topic message -> hello,5
receive topic message -> hello,5
receive topic message -> hello,6
receive topic message -> hello,6
receive topic message -> hello,7
receive topic message -> hello,7
receive topic message -> hello,8
receive topic message -> hello,8
receive topic message -> hello,9
receive topic message -> hello,9
2、将PublishService中发送topic交换机的代码注释,打开发送direct交换机的代码,如下所示:
@Component
public class PublishService {@Autowiredprivate RabbitTemplate rabbitTemplate;public void send(String msg) {//rabbitTemplate.convertAndSend("MEC1", "test.aaa", msg);//rabbitTemplate.convertAndSend("MEC1", "test.bbb", msg);rabbitTemplate.convertAndSend("MEC2", "test.aaa", msg);rabbitTemplate.convertAndSend("MEC2", "test.bbb", msg);}
}
同样运行启动程序,打印如下所示:
receive direct message -> hello,0
receive direct message -> hello,1
receive direct message -> hello,2
receive direct message -> hello,3
receive direct message -> hello,4
receive direct message -> hello,5
receive direct message -> hello,7
receive direct message -> hello,6
receive direct message -> hello,8
receive direct message -> hello,9
虽然发送了两组routingKey=test.aaa和routingKey=test.bbb的消息,但是只打印了test.aaa这个routingKey的消息。因为我们的监听器那里只绑定了一次routingKey。
3、将代码UpMessageListener.java中的另一个绑定routingKey的代码注释打开,运行:
public class UpMessageListener {@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "queue1",durable = "true"), exchange = @Exchange(value="MEC1",type = ExchangeTypes.TOPIC),key = "test.#")})public void topicHandler(Message message,Channel channel) throws IOException{System.out.println("receive topic message -> "+new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "queue2",durable = "true"), exchange = @Exchange(value="MEC2",type = ExchangeTypes.DIRECT),key = "test.aaa")})public void directHandler(Message message,Channel channel) throws IOException{System.out.println("receive direct message -> "+new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "queue2",durable = "true"), exchange = @Exchange(value="MEC2",type = ExchangeTypes.DIRECT),key = "test.bbb")})public void directHandler2(Message message,Channel channel) throws IOException{System.out.println("receive direct message -> "+new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);}}
这次运行就打印了20次消息:
receive direct message -> hello,0
receive direct message -> hello,1
receive direct message -> hello,0
receive direct message -> hello,2
receive direct message -> hello,3
receive direct message -> hello,1
receive direct message -> hello,4
receive direct message -> hello,3
receive direct message -> hello,2
receive direct message -> hello,5
receive direct message -> hello,7
receive direct message -> hello,4
receive direct message -> hello,5
receive direct message -> hello,6
receive direct message -> hello,6
receive direct message -> hello,7
receive direct message -> hello,8
receive direct message -> hello,8
receive direct message -> hello,9
receive direct message -> hello,9
至此,示例结束,再回过头来想想direct和topic类型交换机的区别,其实在生产者端几乎完全没有区别,主要在于消费者端这里,消费者要去消费routingKey,direct只能一一对应消费单个的routingKey,而topic可以使用通配符*和#来匹配多个routingKey。至于他们绑定到queue上,是一个还是多个,他们之间又没有区别。
他们两者与fanout的区别是一个有routingKey,一个没有。
rabbitmq中交换机类型direct和topic的区别相关推荐
- RabbitMQ的交换机类型和工作模式
RabbitMQ的交换机类型有四种 1.direct 直流交换机: 根据消息的路由键routingkey,将消息以完全匹配的方式路由到指定的队列中. 这里的匹配指的是消息本身携带的路由键和队列与交换机 ...
- RabbitMQ中交换机的几种模式
目录 简述 交换机模式 Fanout模式 Direct模式 Topic模式 Headers模式 简述 生产者不直接跟队列打交道,而是通过交换机.交换机类似于生产者和队列直接的一个管理者,它将生产的消息 ...
- oracle 日期 区别,oracle中日期类型 to_date 和to_timestamp什么区别啊?
1.to_date() 和to_timestamp()区别 由于oracle中date类型只支持到秒,不支持到毫秒,所以to_date()不能取到毫秒.如果要取到毫秒,oracle 9i以上版本,可以 ...
- 003 Rabbitmq中交换机的类型
一 注意点 在Rabbitmq之中,存在绑定键和路由键的概念. [1]绑定键 : 交换机和队列关系的一种描述. [2]路由键: 消息之中消息标签的内容,描述了消息最终到达哪些队列之中. 在Rabbit ...
- python中序列类型和数组之间的区别_「Python」序列构成的数组
一.Python 标准库的序列类型分为: 容器序列: 能够存放不同类型数据的序列(list.tuple.collections.deque). 扁平序列: 只能容纳一种类型的数据(str.bytes. ...
- rabbitmq中的队列transient和durable的区别
Durablity:持久dao化选项,duDurable(持久化保存zhi),Transient(即时保存), 持久化保存会dao在RabbitMQ宕机或者重启专后,未消费的消息仍然属存在,即时保存在 ...
- RabbitMQ中的虚拟主机、交换机、消息队列、绑定、消息
虚拟主机(virtual host ) 虚拟地址,用于进行逻辑隔离,最上层的消息路由,一个 virtual host 里面可以有若干个 exchange 和 queue,但是里面不能有相同名称的 ex ...
- RabbitMQ交换机类型
RabbitMQ交换机类型 一.Direct Exchange(直连交换机) 二. Fanout Exchange(扇型交换机) 三.Topic Exchange(主题交换机) 四.Headers E ...
- RabbitMQ交换机(Fanout、Direct、Topic)三种模式详解
一. 交换机 1.1 Exchanges 1.1.1 Exchanges概念 RabbitMQ 消息传递模型的核心思想是: 生产者生产的消息从不会直接发送到队列.实际上,通常生产 者甚至都不知道这 ...
- RabbitMQ指南之四:路由(Routing)和直连交换机(Direct Exchange)
在上一章中,我们构建了一个简单的日志系统,我们可以把消息广播给很多的消费者.在本章中我们将增加一个特性:我们可以订阅这些信息中的一些信息.例如,我们希望只将error级别的错误存储到硬盘中,同时可以将 ...
最新文章
- 知乎社区核心业务 Golang 化实践
- pytest使用简介
- share extension 不显示_这几项超好用的云开发扩展能力,别说你还不知道!
- Py之playsound:playsound的简介、安装、使用方法之详细攻略
- vue中Router的封装以及使用
- python 创建子类_python创建子类的方法分析
- docker centos 环境 安装 python
- 99行不用指针 c语言贪食蛇,关于C语言指针的问题
- 为什么新装的mysql5.7服务无法启动_Mysql5.7为什么无法启动?请大家帮忙
- Swift 4 和 Objective-C 在同一个工程里的混搭编程的方法
- JavaScript 虚拟键盘 A-Keyboard
- 物联网网络编程、Web编程综述
- 缠中说禅形态挖掘之九笔形态
- Webcontent 和WebRoot的区别
- 通过注册表改变“我的文档”等的默认位置
- Ubuntu17.04系统安装必备软件与存在的问题
- Pytorch:三、数据的迭代训练(猫狗)
- [转]斗鱼大数据搭建的经验和坑
- python派森编程软件_《派森》(Python)
- VirtualBox安装虚拟机并为其装系统