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的区别相关推荐

  1. RabbitMQ的交换机类型和工作模式

    RabbitMQ的交换机类型有四种 1.direct 直流交换机: 根据消息的路由键routingkey,将消息以完全匹配的方式路由到指定的队列中. 这里的匹配指的是消息本身携带的路由键和队列与交换机 ...

  2. RabbitMQ中交换机的几种模式

    目录 简述 交换机模式 Fanout模式 Direct模式 Topic模式 Headers模式 简述 生产者不直接跟队列打交道,而是通过交换机.交换机类似于生产者和队列直接的一个管理者,它将生产的消息 ...

  3. oracle 日期 区别,oracle中日期类型 to_date 和to_timestamp什么区别啊?

    1.to_date() 和to_timestamp()区别 由于oracle中date类型只支持到秒,不支持到毫秒,所以to_date()不能取到毫秒.如果要取到毫秒,oracle 9i以上版本,可以 ...

  4. 003 Rabbitmq中交换机的类型

    一 注意点 在Rabbitmq之中,存在绑定键和路由键的概念. [1]绑定键 : 交换机和队列关系的一种描述. [2]路由键: 消息之中消息标签的内容,描述了消息最终到达哪些队列之中. 在Rabbit ...

  5. python中序列类型和数组之间的区别_「Python」序列构成的数组

    一.Python 标准库的序列类型分为: 容器序列: 能够存放不同类型数据的序列(list.tuple.collections.deque). 扁平序列: 只能容纳一种类型的数据(str.bytes. ...

  6. rabbitmq中的队列transient和durable的区别

    Durablity:持久dao化选项,duDurable(持久化保存zhi),Transient(即时保存), 持久化保存会dao在RabbitMQ宕机或者重启专后,未消费的消息仍然属存在,即时保存在 ...

  7. RabbitMQ中的虚拟主机、交换机、消息队列、绑定、消息

    虚拟主机(virtual host ) 虚拟地址,用于进行逻辑隔离,最上层的消息路由,一个 virtual host 里面可以有若干个 exchange 和 queue,但是里面不能有相同名称的 ex ...

  8. RabbitMQ交换机类型

    RabbitMQ交换机类型 一.Direct Exchange(直连交换机) 二. Fanout Exchange(扇型交换机) 三.Topic Exchange(主题交换机) 四.Headers E ...

  9. RabbitMQ交换机(Fanout、Direct、Topic)三种模式详解

    一. 交换机 1.1 Exchanges 1.1.1 Exchanges概念 ​ RabbitMQ 消息传递模型的核心思想是: 生产者生产的消息从不会直接发送到队列.实际上,通常生产 者甚至都不知道这 ...

  10. RabbitMQ指南之四:路由(Routing)和直连交换机(Direct Exchange)

    在上一章中,我们构建了一个简单的日志系统,我们可以把消息广播给很多的消费者.在本章中我们将增加一个特性:我们可以订阅这些信息中的一些信息.例如,我们希望只将error级别的错误存储到硬盘中,同时可以将 ...

最新文章

  1. 知乎社区核心业务 Golang 化实践
  2. pytest使用简介
  3. share extension 不显示_这几项超好用的云开发扩展能力,别说你还不知道!
  4. Py之playsound:playsound的简介、安装、使用方法之详细攻略
  5. vue中Router的封装以及使用
  6. python 创建子类_python创建子类的方法分析
  7. docker centos 环境 安装 python
  8. 99行不用指针 c语言贪食蛇,关于C语言指针的问题
  9. 为什么新装的mysql5.7服务无法启动_Mysql5.7为什么无法启动?请大家帮忙
  10. Swift 4 和 Objective-C 在同一个工程里的混搭编程的方法
  11. JavaScript 虚拟键盘 A-Keyboard
  12. 物联网网络编程、Web编程综述
  13. 缠中说禅形态挖掘之九笔形态
  14. Webcontent 和WebRoot的区别
  15. 通过注册表改变“我的文档”等的默认位置
  16. Ubuntu17.04系统安装必备软件与存在的问题
  17. Pytorch:三、数据的迭代训练(猫狗)
  18. [转]斗鱼大数据搭建的经验和坑
  19. python派森编程软件_《派森》(Python)
  20. VirtualBox安装虚拟机并为其装系统

热门文章

  1. 网站启用CDN加速对百度SEO排名有什么影响?
  2. 用js实现在文本框中检测字数和限制字数功能
  3. php756中医,百人诈骗团伙冒充老中医微信钓鱼九千余人被骗
  4. pythonrestapicctv_Python Web服务(15) 持续更新
  5. xxxx-xx-xx系统应用(周)巡检报告模版
  6. 怎么查看计算机簇大小,分区格式与簇的大小讲解
  7. 微软、google、IBM的某些招聘试题
  8. 云计算存在哪些安全问题
  9. java 将海外时区转换为北京时区
  10. 星星之火OIer:TunaParetoUnija