前言

来了解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. 算法学习笔记,几个简单的Demo

    算法初学的一些心得 前言:现在工作也快一年多了,有时间下班回家会学学算法,陆陆续续也接触了一些 貌似我知道的就冒泡排序其他的都不是很了解 最近买了一本书,边学边记录吧! 一些常用的方法 暴力破解 下面 ...

  2. Linux系统安装MySQL——.rpm版

    0.环境 本文操作系统: CentOS 7.2.1511 x86_64MySQL 版本: 5.7.13 1.下载 MySQL 官方的 Yum Repository 从 MySQL 官网选取合适的 My ...

  3. mysql查看视图用户

    select `DEFINER` from  information_schema.VIEWS;

  4. vim批量注释和反注释快捷键

    vim批量注释和反注释快捷键 我是个vim新手,非常喜欢这个工具,因为纯手工操作吧.可是有些快捷键还是不知道,写Python的时候经常要调试,会批量注释掉一些代码,vim不像pycharm那样 Ctr ...

  5. 基于SDN网络的负载均衡研究与实现

    为什么需要软件定义网络 1.网络缺乏可扩展性,创新正在停滞不前.   我们最新的研究发现,几乎每两个组织中就有一个认为需要将网络功能扩展为采用SDN的主要业务触发因素,而不是其他催化剂.这一统计数据一 ...

  6. 解决Oracle.DataAccess.Client.OracleConnection”的类型初始值设定项引发异常。

    解决Oracle.DataAccess.Client.OracleConnection”的类型初始值设定项引发异常. 这个问题他们说是oracle的版本问题 但是好像不是...(我感觉VS版本问题,我 ...

  7. lr参数化

    为什么做参数化? 数据库校验:注册用户时会看数据库有没有这个账号 应用程序校验:pc端qq登陆,一个账号只能登陆一台电脑 1.数据库或应用程序提交值的唯一性校验 数据库查询过程: 1.语法检查.语义检 ...

  8. java并发笔记之java线程模型

    警告⚠️:本文耗时很长,先做好心理准备 java当中的线程和操作系统的线程是什么关系? 猜想: java thread —-对应-—> OS thread Linux关于操作系统的线程控制源码: ...

  9. Shiro权限管理框架(一):Shiro的基本使用

    首发地址:https://www.guitu18.com/post/2019/07/26/43.html 核心概念 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码 ...

  10. java的System.currentTimeMillis()和System.nanoTime

    纳秒 ns(nanosecond):纳秒, 时间单位.一秒的10亿分之一,即等于10的负9次方秒.常用作 内存读写速度的单位,其前面数字越小则表示速度越快.   1纳秒=1000 皮秒   1纳秒 = ...