前言

来了解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. C#跟Lua如何超高性能传递数据

    前言 在UWA学堂上线那天,我买了招文勇这篇Lua交互的课程,19块还算值,但是前段时间太忙,一直没空研究,他的demo是基于xlua的,今天终于花了大半天时间在tolua下跑起来了,记录一下我的理解 ...

  2. [分享] 一款极简单的 BaseEntity CRUD 方法

    前言 尝试过 ado.net.dapper.ef,以及Repository仓储,甚至自己还写过生成器工具,以便做常规CRUD操作. 它们日常操作不方便之处: 每次使用前需要声明,再操作: 很多人一个实 ...

  3. vijos p1484 ISBN号码

    #include<iostream>#include<string>#include<cctype>using namespace std;int main() { ...

  4. Nodejs监控Apple召回计划&邮件提醒

    最近,我的MacBook Pro 2015款13寸电池膨胀了 把笔记本平放在桌面,四个脚中的前两个无法落地,笔记本盖合上之后,屏幕上会印上键盘的纹路,也就是说,笔记本C面D面变形了,已经购买超过3年, ...

  5. hive show databases 添加条件

    show databases like 'test012301' ; 通配符: show databases like 'a*';

  6. Android CHM文件阅读器

    CHM格式是1998年微软推出的基于HTML文件特性的帮助文件系统.以替代早先的winHelp帮助系统,它也是一种超文本标识语言.在Windows 98中把CHM类型文件称作“已编译的HTML帮助文件 ...

  7. Codeforces1144D(D题)Equalize Them All

    D. Equalize Them All You are given an array aa consisting of nn integers. You can perform the follow ...

  8. 华三F100 系列防火墙 - 浮动路由联动NQA 实现双线路自动切换

    公司 有两条公网线路,一条移动作为日常主用线路,一条联通作为备用线路. 为了实现主备线路自动切换,配置了浮动路由 但浮动路由只能在 主用接口为down状态时才能浮出接管默认路由.如果故障为非物理链路故 ...

  9. Java入门 面向对象第一天

    面向对象 人为抽象的一种编程模型,在理解面向对象的代码时要按照抽象的模型来理解,不能只从代码字面来理解复杂的问题,学会拆分成一个一个独立的小问题,通过解决每一个小问题,最后解决一个大问题 类 类是事物 ...

  10. 前后端分离 之vue-cli 搭建项目mac 系统讲解

    前端项目搭建必备技术 webpack nodejs 搭建 vue-cli 的安装 以上技术自行了解安装 一:创建前端项目 采用vue-cli 脚手架 1:终端执行如下命令 vue init webpa ...