前言

来了解RabbitMQ一个重要的概念:Exchange交换机

1. Exchange概念

  • Exchange:接收消息,并根据路由键转发消息所绑定的队列。

蓝色框:客户端发送消息至交换机,通过路由键路由至指定的队列。

黄色框:交换机和队列通过路由键有一个绑定的关系。

绿色框:消费端通过监听队列来接收消息。

2. 交换机属性

Name:交换机名称

Type:交换机类型——direct、topic、fanout、headers、sharding(此篇不讲)

Durability:是否需要持久化,true为持久化

Auto Delete:当最后一个绑定到Exchange上的队列删除后,自动删除该Exchange

Internal:当前Exchange是否用于RabbitMQ内部使用,默认为false

Arguments:扩展参数,用于扩展AMQP协议自定制化使用

3. Direct Exchange(直连)

  • 所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue

注意:Direct模式可以使用RabbitMQ自带的Exchange:default Exchange,所以不需要将Exchange进行任何绑定(binding)操作,消息传递时,RouteKey必须完全匹配才会被队列接收,否则该消息会被抛弃。

重点:routing key与队列queues 的key保持一致,即可以路由到对应的queue中。

3.1 代码演示

生产端:


/**
*
* @ClassName: Producer4DirectExchange
* @Description: 生产者
* @author Coder编程
* @date2019年7月19日 下午22:15:52
*
*/
public class Producer4DirectExchange { public static void main(String[] args) throws Exception { //1创建ConnectionFactory
Connection connection = ConnectionUtils.getConnection();
//2创建Channel
Channel channel = connection.createChannel();
//3 声明
String exchangeName = "test_direct_exchange";
String routingKey = "test.direct";
//4 发送
String msg = "Coder编程 Hello World RabbitMQ 4 Direct Exchange Message ... ";
channel.basicPublish(exchangeName, routingKey , null , msg.getBytes());
}
}

消费端:


/**
*
* @ClassName: Consumer4DirectExchange
* @Description: 消费者
* @author Coder编程
* @date2019年7月19日 下午22:18:52
*
*/
public class Consumer4DirectExchange { public static void main(String[] args) throws Exception { //创建ConnectionFactory
Connection connection = ConnectionUtils.getConnection();
Channel channel = connection.createChannel();
//声明
String exchangeName = "test_direct_exchange";
String exchangeType = "direct";
String queueName = "test_direct_queue";
String routingKey = "test.direct"; //表示声明了一个交换机
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
//表示声明了一个队列
channel.queueDeclare(queueName, false, false, false, null);
//建立一个绑定关系:
channel.queueBind(queueName, exchangeName, routingKey); //durable 是否持久化消息
QueueingConsumer consumer = new QueueingConsumer(channel);
//参数:队列名称、是否自动ACK、Consumer
channel.basicConsume(queueName, true, consumer);
//循环获取消息
while(true){
//获取消息,如果没有消息,这一步将会一直阻塞
Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("收到消息:" + msg);
}
}
}

测试结果:

注意需要routingKey保持一致。可以自己尝试修改routingkey,是否能收到消息。

4. Topic Exchange

  • 所有发送到Topic Exchange的消息被转发到所有管线RouteKey中指定Topic的Queue上
  • Exchange将RouteKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic

注意:可以使用通配符进行模糊匹配

符号 "#" 匹配一个或多个词

符号 "" 匹配不多不少一个词

例如:"log.#" 能够匹配到 "log.info.oa"

"log.
" 只会匹配到 "log.error"

在一堆消息中,每个不同的队列只关心自己需要的消息。

4.1 代码演示

生产端:


/**
*
* @ClassName: Producer4TopicExchange
* @Description: 生产者
* @author Coder编程
* @date2019年7月19日 下午22:32:41
*
*/
public class Producer4TopicExchange { public static void main(String[] args) throws Exception { //1创建ConnectionFactory
Connection connection = ConnectionUtils.getConnection();
//2创建Channel
Channel channel = connection.createChannel();
//3声明
String exchangeName = "test_topic_exchange";
String routingKey1 = "user.save";
String routingKey2 = "user.update";
String routingKey3 = "user.delete.abc";
//4发送
String msg = "Coder编程 Hello World RabbitMQ 4 Topic Exchange Message ...";
channel.basicPublish(exchangeName, routingKey1 , null , msg.getBytes());
channel.basicPublish(exchangeName, routingKey2 , null , msg.getBytes());
channel.basicPublish(exchangeName, routingKey3 , null , msg.getBytes());
channel.close();
connection.close();
}
}

消费端:


/**
*
* @ClassName: Consumer4TopicExchange
* @Description: 消费者
* @author Coder编程
* @date2019年7月19日 下午22:37:12
*
*/
public class Consumer4TopicExchange { public static void main(String[] args) throws Exception { //创建ConnectionFactory
Connection connection = ConnectionUtils.getConnection(); Channel channel = connection.createChannel();
// 声明
String exchangeName = "test_topic_exchange";
String exchangeType = "topic";
String queueName = "test_topic_queue";
//String routingKey = "user.*";
String routingKey = "user.*";
// 1 声明交换机
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
// 2 声明队列
channel.queueDeclare(queueName, false, false, false, null);
// 3 建立交换机和队列的绑定关系:
channel.queueBind(queueName, exchangeName, routingKey); //durable 是否持久化消息
QueueingConsumer consumer = new QueueingConsumer(channel);
//参数:队列名称、是否自动ACK、Consumer
channel.basicConsume(queueName, true, consumer);
//循环获取消息
while(true){
//获取消息,如果没有消息,这一步将会一直阻塞
Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("收到消息:" + msg);
}
}
}

测试结果:

注意一个问题:需要进行解绑

5. Fanout Exchange

  • 不处理路由键,只需要简单的将队里绑定到交换机上
  • 发送到交换机的消息都会被转发到与该交换机绑定的所有队列上
  • Fanout交换机转发消息是最快的

5.1 代码演示

生产端:



/**
*
* @ClassName: Producer4FanoutExchange
* @Description: 生产者
* @author Coder编程
* @date2019年7月19日 下午23:01:16
*
*/
public class Producer4FanoutExchange { public static void main(String[] args) throws Exception { //1创建ConnectionFactory
Connection connection = ConnectionUtils.getConnection();
//2 创建Channel
Channel channel = connection.createChannel();
//3 声明
String exchangeName = "test_fanout_exchange";
//4 发送
for(int i = 0; i < 10; i ++) {
String msg = "Coder 编程 Hello World RabbitMQ 4 FANOUT Exchange Message ...";
channel.basicPublish(exchangeName, "", null , msg.getBytes());
}
channel.close();
connection.close();
} }

消费端:


/**
*
* @ClassName: Consumer4FanoutExchange
* @Description: 消费者
* @author Coder编程
* @date2019年7月19日 下午23:21:18
*
*/
public class Consumer4FanoutExchange { public static void main(String[] args) throws Exception { //创建ConnectionFactory
Connection connection = ConnectionUtils.getConnection(); Channel channel = connection.createChannel();
// 声明
String exchangeName = "test_fanout_exchange";
String exchangeType = "fanout";
String queueName = "test_fanout_queue";
String routingKey = ""; //不设置路由键
channel.exchangeDeclare(exchangeName, exchangeType, true, false, false, null);
channel.queueDeclare(queueName, false, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey); //durable 是否持久化消息
QueueingConsumer consumer = new QueueingConsumer(channel);
//参数:队列名称、是否自动ACK、Consumer
channel.basicConsume(queueName, true, consumer);
//循环获取消息
while(true){
//获取消息,如果没有消息,这一步将会一直阻塞
Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("收到消息:" + msg);
}
}
}

测试结果:


6. 其他

6.1 Bingding —— 绑定

  • Exchange和Exchange、Queue之间的连接关系
  • Bingding可以包含RoutingKey或者参数

6.2 Queue——消息队列

  • 消息队列,实际存储消息数据
  • Durability:是否持久化,Durable:是 ,Transient:否
  • Auto delete:如选yes,代表当最后一个监听被移除之后,该Queue会自动被删除。

6.3 Message——消息

  • 服务器与应用程序之间传送的数据
  • 本质上就是一段数据,由Properties和Payload(Body)组成
  • 常用属性:delivery mode、headers(自定义属性)

6.4 其他属性

content_type、content_encoding、priority

correlation_id、reply_to、expiration、message_id

timestamp、type、user_id、app_id、cluster_id

6.5 Virtual Host虚拟主机

  • 虚拟地址,用于进行逻辑隔离,最上层的消息路由
  • 一个Virtual Host里面可以有若干个Exchange和Queue
  • 同一个Virtual Host里面不能有相同名称的Exchange或Queue

7. 总结

RabbitMQ的概念、安装与使用、管控台操作、结合RabbitMQ的特性、Exchange、Queue、Binding

、RoutingKey、Message进行核销API的讲解,通过本章的学习,希望大家对RabbitMQ有一个初步的认识。

文末

欢迎关注个人微信公众号:Coder编程

获取最新原创技术文章和免费学习资料,更有大量精品思维导图、面试资料、PMP备考资料等你来领,方便你随时随地学习技术知识!

新建了一个qq群:315211365,欢迎大家进群交流一起学习。谢谢了!也可以介绍给身边有需要的朋友。

文章收录至

Github: https://github.com/CoderMerlin/coder-programming

Gitee: https://gitee.com/573059382/coder-programming

欢迎关注并star~

参考文章:

《RabbitMQ消息中间件精讲》

推荐文章:

消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!

消息中间件——RabbitMQ(四)命令行与管控台的基本操作!

消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!

消息中间件——RabbitMQ(六)理解Exchange交换机核心概念!的更多相关文章

  1. 理解maven的核心概念

    原文出处:http://www.cnblogs.com/holbrook/archive/2012/12/24/2830519.html 好久没进行java方面的开发了,最近又完成了一个java相关的 ...

  2. Docker入门——理解Docker的核心概念

    1 前言 相信不少人听过这么一句话: 人类的本质是复读机. 在软件开发领域也一样,我们总是想寻找更好地方式复制优秀的逻辑或系统.最核心的方法是抽取通用逻辑和组件,把差异化的东西接口化或配置化,达到复用 ...

  3. 轻松理解 Kubernetes 的核心概念

    Kubernetes 迅速成为云环境中软件部署和管理的新标准. 与强大的功能相对应的是陡峭的学习曲线. 本文将提供 Kubernetes 的简化视图,从高处观察其中的重要组件,以及他们的关联. 硬件 ...

  4. Maven 专题(六):Maven核心概念详解(二)

    5 仓库 5.1 分类 [1]本地仓库:为当前本机电脑上的所有 Maven 工程服务.[2]远程仓库:        (1)私服:架设在当前局域网环境下,为当前局域网范围内的所有 Maven 工程服务 ...

  5. 消息中间件——RabbitMQ(七)高级特性全在这里!(上)

    前言 前面我们介绍了RabbitMQ的安装.各大消息中间件的对比.AMQP核心概念.管控台的使用.快速入门RabbitMQ.本章将介绍RabbitMQ的高级特性.分两篇(上/下)进行介绍. 消息如何保 ...

  6. 消息中间件——RabbitMQ(八)高级特性全在这里!(下)

    前言 上一篇消息中间件--RabbitMQ(七)高级特性全在这里!(上)中我们介绍了消息如何保障100%的投递成功?,幂等性概念详解,在海量订单产生的业务高峰期,如何避免消息的重复消费的问题?,Con ...

  7. 消息中间件——RabbitMQ(九)RabbitMQ整合Spring AMQP实战!(全)

    前言 1. AMQP 核心组件 RabbitAdmin SpringAMQP声明 RabbitTemplate SimpleMessageListenerContainer MessageListen ...

  8. webpack的四个核心概念介绍

    前言 webpack 是一个当下最流行的前端资源的模块打包器.当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后 ...

  9. 通过核心概念了解webpack工作机制

    webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency gr ...

随机推荐

  1. [记录]Shell并发模式批量安装saltstack的脚本

    SaltStack+Shell: salt-master的配置: #cat /etc/salt/master user: root auto_accept: True salt-minion的配置(支 ...

  2. o2优化(手动)

    #pragma GCC optimize(2) 将这句话放到程序开头即可

  3. NOIp2018 TG day1 T2暨洛谷P5020 货币系统:题解

    题目链接:https://www.luogu.org/problemnew/show/P5020 这道题感觉比较水啊,身为普及组蒟蒻都不费力的做出来了,而且数据范围应该还能大一些,n起码几万几十万都不 ...

  4. 总结暨JAVAWEB学习开篇(一)

    匆匆,距上一篇博客已经过去7月有余,遂作文一篇总结暨JAVAWEB学习开篇. 1. 啃英文新概念.在多方讨教英语大佬后改变学习方式,通过背诵英文书籍以及多听英文录音来学习,效果还不错(等真正有成效了跟 ...

  5. ping(网络诊断工具)

    ping(网络诊断工具) Ping是Windows下的一个命令,在Unix和Linux下也有这个命令.ping也属于一个通信协议,是TCP/IP协议的一部分.利用"ping"命令可 ...

  6. C#的DateTime得到特定日期

    //指定时间 DateTime dt = new DateTime(2016, 6, 1); //当前时间 DateTime dt = DateTime.Now; //本周周一 DateTime st ...

  7. 关于Spring的JDBC连接mysql(与传统jdbc比较)

    Spring的jdbc与Hibernate,Mybatis相比较,功能不是特别强大,但是在小型项目中,也到还是比较灵活简单. 首先可以看看一下传统的jdbc是如何操作的呢 传统JDBC 首先呢先要创建 ...

  8. oracle查询截至到当前日期月份所在年份的所有月份

    SELECT to_number(TO_CHAR(add_months(trunc(sysdate, 'yy'), ROWNUM - 1), 'MM')) as month FROM DUALCONN ...

  9. light oj 1159 - Batman LCS

    学过简单动态规划的人应该对最长公共子序列的问题很熟悉了,这道题只不过多加了一条字符串变成三条了,还记得,只要把状态变成三维的即可. //http://lightoj.com/volume_showpr ...

  10. Ubuntu 系统如何用pycharm开发python—OpenCV