在上一篇博客《RabbitMQ入门:发布/订阅(Publish/Subscribe)》中,我们认识了fanout类型的exchange,它是一种通过广播方式发送消息的路由器,所有和exchange建立的绑定关系的队列都会接收到消息。但是有一些场景只需要订阅到一部分消息,这个时候就不能使用fanout 类型的exchange了,这个就引出来今天的“猪脚”--Direct Exchange,通过Routing Key来决定需要将消息发送到哪个或者哪些队列中。

接下来请收看详细内容:

Direct Exchange(直接路由器)

多重绑定

代码实例

一、Direct Exchange(直接路由器)

在上文中介绍exchange的时候,对direct exchange进行了简单介绍,它是一种完全按照routing key(路由关键字)进行投递的:当消息中的routing key和队列中的binding key完全匹配时,才进行会将消息投递到该队列中。这里提到了一个routing key和binding key(绑定关键字),是什么东东?

routing key:

在发送消息的时候,basicPublish的第二个参数就是routing key,由于上次是fanout 类型的exchange 进行广播方式投递,这个字段不会影响投递结果,因此我们这里就传入了“”,但是在direct 类型的exchange中我们就不能传入""了,需要指定具体的关键字。

binding key:

我们在前文中建立绑定关系的时候,queueBind的第三个参数就是绑定关键字

我们声明direact exchange的时候使用:

二、多重绑定

多个队列以相同的绑定键绑定到同一个路由器的情况,我们称之为多重绑定。

工作模型为(P代表生产者,X代表路由器,红色的Q代表队列,C代表消费者):

三、代码实例

预备知识了解完了,现在来写个程序感受下。

生产者

public classLogDirectSender {//exchange名字

public static String EXCHANGE_NAME = "directExchange";public static voidmain(String[] args) {

ConnectionFactory factory= newConnectionFactory();

factory.setHost("localhost");

Connection connection= null;

Channel channel= null;try{//1.创建连接和通道

connection =factory.newConnection();

channel=connection.createChannel();//2.为通道声明direct类型的exchange

channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);//3.发送消息到指定的exchange,队列指定为空,由exchange根据情况判断需要发送到哪些队列

String routingKey = "debug";

String msg= " hello rabbitmq, I am " +routingKey;

channel.basicPublish(EXCHANGE_NAME, routingKey,null, msg.getBytes());

System.out.println("product send a msg: " +msg);

}catch(IOException e) {

e.printStackTrace();

}catch(TimeoutException e) {

e.printStackTrace();

}finally{//4.关闭连接

if (channel != null) {try{

channel.close();

}catch(IOException e) {

e.printStackTrace();

}catch(TimeoutException e) {

e.printStackTrace();

}

}if (connection != null) {try{

connection.close();

}catch(IOException e) {

e.printStackTrace();

}

}

}

}

}

和上次博客中生产者的区别就是黑字粗体部分:1.路由器类型改为direct 2.消息发布的时候指定了routing key

消费者

public classLogDirectReciver {public static voidmain(String[] args) {

ConnectionFactory factory= newConnectionFactory();

factory.setHost("localhost");

Connection connection= null;

Channel channel= null;try{//1.创建连接和通道

connection =factory.newConnection();

channel=connection.createChannel();//2.为通道声明direct类型的exchange

channel.exchangeDeclare(LogDirectSender.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);//3.创建随机名字的队列

String queueName =channel.queueDeclare().getQueue();//4.建立exchange和队列的绑定关系

String[] bindingKeys = { "error", "info", "debug"};//String[] bindingKeys = { "error" };

for (int i = 0; i < bindingKeys.length; i++) {

channel.queueBind(queueName, LogDirectSender.EXCHANGE_NAME, bindingKeys[i]);

System.out.println(" **** LogDirectReciver keep alive ,waiting for " +bindingKeys[i]);

}//5.通过回调生成消费者并进行监听

Consumer consumer = newDefaultConsumer(channel) {

@Overridepublic voidhandleDelivery(String consumerTag, Envelope envelope,

com.rabbitmq.client.AMQP.BasicProperties properties,byte[] body) throwsIOException {//获取消息内容然后处理

String msg = new String(body, "UTF-8");

System.out.println("*********** LogDirectReciver" + " get message :[" + msg + "]");

}

};//6.消费消息

channel.basicConsume(queueName, true, consumer);

}catch(IOException e) {

e.printStackTrace();

}catch(TimeoutException e) {

e.printStackTrace();

}

}

}

和上次博客中消费者的区别就是黑字粗体部分:1.路由器类型改为direct 2.建立绑定关系的时候指定了binding key

执行消费者,控制台log打印如下:

**** LogDirectReciver keep alive ,waiting forerror**** LogDirectReciver keep alive ,waiting forinfo**** LogDirectReciver keep alive ,waiting for debug

这个消费者我们视为消费者1,它会接收error,info,debug三个关键字的消息。

将String[] bindingKeys = { "error", "info", "debug" };改为String[] bindingKeys = { "error" };,然后再运行一次消费者。控制台log打印如下:

**** LogDirectReciver keep alive ,waiting for error

这个消费者我们视为消费者2,它只会接收error 关键字的消息。

执行生产者,然后将String routingKey = "debug";的值分别改为“info"和"error",然后分别执行,这样一共执行了三次生产者

第一次执行:

product send a msg: hello rabbitmq, I am debug

第二次执行:

product send a msg: hello rabbitmq, I am info

第三次执行:

product send a msg: hello rabbitmq, I am error

再次查看两个消费者的控制台log:

消费者1:**** LogDirectReciver keep alive ,waiting forerror**** LogDirectReciver keep alive ,waiting forinfo**** LogDirectReciver keep alive ,waiting fordebug***********LogDirectReciver get message :[ hello rabbitmq, I am debug]***********LogDirectReciver get message :[ hello rabbitmq, I am info]***********LogDirectReciver get message :[ hello rabbitmq, I am error]

消费者2:**** LogDirectReciver keep alive ,waiting forerror*********** LogDirectReciver get message :[ hello rabbitmq, I am error]

查看RabbitMQ管理页面

exchanges标签页里面多了个direct类型的路由器。进入详细页面:

有4个绑定关系,其中三个的队列是同一个。切换到Queues标签页:

有两个临时队列。

如果关掉消费者1和消费者2,会发现队列自动删除了,绑定关系也不存在了。

java 路由_RabbitMQ入门:路由(Routing)相关推荐

  1. python 路由转发_RabbitMQ之路由键转发消息

    RabbitMQ学习 消息队列:目前流行的有 Kafka.RabbitMQ.ActiveMQ等 功能:为了解决消息的分布式消费,完成项目.服务之间的解耦动作.消息的生产者与消费者之间完全采用异步通信方 ...

  2. SAP UI5 应用开发教程之三十一 - SAP UI5 的路由历史和路由回退(Routing back and history)试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  3. openwrt 格式化_OPENWRT路由固件入门食用教程S2:磁盘挂载及分区,网络共享,脱机下载。...

    OPENWRT路由固件入门食用教程S2:磁盘挂载及分区,网络共享,脱机下载. 2021-01-19 18:16:11 17点赞 127收藏 15评论 是返乡过年?还是就地过年?最新一届#双面过节指南# ...

  4. 十、路由信息协议RIP(Routing Information Protocol)

    路由信息协议RIP(Routing Information Protocol) 路由协议分类 路由学习的方式进行分类: 静态路由 动态路由 算法分类(动态路由分类): 距离矢量路由协议:RIP.EIG ...

  5. 段路由SR(Segment Routing)是基于源路由理念而设计的在网络上转发数据包的一种技术架构

    一.SR背景 段路由SR(Segment Routing)是基于源路由理念而设计的在网络上转发数据包的一种技术架构. SR-MPLS可以通过多个MPLS形成路径(基于标签转发)     SRv6可以通 ...

  6. vue 创建项目并添加路由(Vue路由入门教学,图文详解)

    注:初学vue,如有错误.请指教,谢谢! 1.vue-cli 1.1 介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统 1.2 下载vue-cli 在命令行下运行 npm ins ...

  7. umi权限路由_umi 入门之项目配置

    umi 项目配置 一.运行配置 约定src/app.tsx为运行配置 配置项目 1.patchRoutes 修改路由,可获得整个路由系统 export function patchRoutes({ r ...

  8. SpringCloud 服务网关 Zuul 自定义路由和排除路由配置

    前言 首先需要说明的是该文是 [带你入门SpringCloud 之 服务网关 Zuul ]的拓展篇,如果还未阅读 [带你入门SpringCloud 之 服务网关 Zuul ]请先阅读完毕后在阅读该文. ...

  9. 基于【IPv6】静态路由和默认路由的配置

    基于IPv6静态路由和默认路由的配置 实验环境: 实验背景:在路由器R1上配置3个环回接口IPv6地址,分别模拟三个不同的IPv6前缀,作为IPV6目标网络,然后,在路由器R2上为三个IPv6前缀配置 ...

最新文章

  1. Visual Studio Code为什么能这么牛X?
  2. 4次迭代!10w行级别数据的Excel导入优化记录
  3. 虚拟成像技术_AI帝国将崛起,国内幻真虚拟成像技术第一家
  4. 通俗讲解:图像傅里叶变换
  5. python查看CNN训练模型参数
  6. c语言1000行代码,【图片】【标题党】论我是如何一分钟写1000行代码的【c语言吧】_百度贴吧...
  7. Kafka-batch.size属性
  8. 蓝桥杯 ADV-90 算法提高 输出日历
  9. STM32 光敏电阻传感器两路AD采集
  10. Check Exception or Uncheck Exception
  11. python交集和补集的符号_python数组并集交集补集
  12. springboot群发邮件问题实例
  13. sass混合器,选择器的继承
  14. Rafy 开源贡献中心 - 组织成立,并试运行一月小结
  15. ARM_NEON_CNN编程 SIMD单指令多数据流 intrinsics指令 内联汇编 CNN卷积网络优化 深度学习优化
  16. 转:告诉你一个真实的数字化
  17. Silverlight游戏设计(Game Design):(十三)帝国时代II (Demo) 之 “战争艺术”②
  18. 为什么在大多数OS中都引入”打开“这一文件系统调用?打开的含义是什么?...
  19. 【labview】限幅子vi +源程序
  20. 银赛电气降低电气开关火灾危险性

热门文章

  1. docker 安装 sqlserver 数据库
  2. Flutter起步之安装
  3. mpvue使用vant Weapp运行npm run build命令打包后失效
  4. asp.net后台管理系统-登陆模块-路由权限控制_1
  5. Java动态代理全面分析
  6. Mybatis框架_part1
  7. 4.openSession() 、 getCurrentSession()与session上下文
  8. Could not load the btn_020.disable.png image referenced from a nib in the bundle with identifier ...
  9. 谈谈Groovy闭包
  10. Container 布局容器