RabbitMQ入门:路由(Routing)
在上一篇博客《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 class LogDirectSender {
// exchange名字
public static String EXCHANGE_NAME = "directExchange"; public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory();
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 class LogDirectReciver { public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory();
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 = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
com.rabbitmq.client.AMQP.BasicProperties properties, byte[] body) throws IOException { // 获取消息内容然后处理
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 for error
**** LogDirectReciver keep alive ,waiting for info
**** 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 for error
**** LogDirectReciver keep alive ,waiting for info
**** LogDirectReciver keep alive ,waiting for debug
*********** 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 for error
*********** LogDirectReciver get message :[ hello rabbitmq, I am error] - 查看RabbitMQ管理页面
exchanges标签页里面多了个direct类型的路由器。进入详细页面:

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

有两个临时队列。
如果关掉消费者1和消费者2,会发现队列自动删除了,绑定关系也不存在了。
RabbitMQ入门:路由(Routing)的更多相关文章
- RabbitMQ入门-路由-有选择的接受消息
比如一个日志系统,之前的处理方式呢,是各种类型(info,error,warning)的消息都发给订阅者,可是实际情况上不一定都需要.可能A需要error,其他的都不需要.那么就引入了今天的处理方式- ...
- RabbitMQ之路由(Routing)【译】
在上一节中,我们创建了一个简单的日志系统,可以广播消息到很多接收者. 这一节,我们将在上一节的基础上加一个功能--订阅部分消息.例如,我们只将严重错误信息写入到日志文件保存在磁盘上,同时我们能将所有的 ...
- RabbitMQ入门到进阶(Spring整合RabbitMQ&SpringBoot整合RabbitMQ)
1.MQ简介 MQ 全称为 Message Queue,是在消息的传输过程中保存消息的容器.多用于分布式系统 之间进行通信. 2.为什么要用 MQ 1.流量消峰 没使用MQ 使用了MQ 2.应用解耦 ...
- RabbitMQ官方中文入门教程(PHP版) 第四部分:路由(Routing)
路由(Routing) 在前面的教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重的错误日 ...
- RabbitMQ 入门教程(PHP版) 第四部分:路由(Routing)
路由(Routing) 在前面的第三部分教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重 ...
- RabbitMQ学习总结 第五篇:路由Routing
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- RabbitMQ入门教程(六):路由选择Routing
原文:RabbitMQ入门教程(六):路由选择Routing 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...
- RabbitMQ 入门系列:3、基础含义:持久化、排它性、自动删除、强制性、路由键。
系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...
- 2.RABBITMQ 入门 - WINDOWS - 生产和消费消息 一个完整案例
关于安装和配置,见上一篇 1.RABBITMQ 入门 - WINDOWS - 获取,安装,配置 公司有需求,要求使用winform开发这个东西(消息中间件),另外还要求开发一个日志中间件,但是也是要求 ...
随机推荐
- [转]Hadoop 读写数据流
Hadoop文件读取 1)客户端通过调用FileSystem对象中的open()函数来读取它做需要的数据.FileSystem是HDFS中DistributedFileSystem的一个实例. 2)D ...
- debian 7上安装svn
1.在终端中直接输入 sudo apt-get install subversion,选择安装即可 2.查看版本命令 svnserve --version(更多命令直接键入svnserve --he ...
- 如何解决安卓(系统版本低) CSS3 动画问题---高性能动画
目前对提升移动端CSS3动画体验的主要方法有几点: 尽可能多的利用硬件能力,如使用3D变形来开启GPU加速 -webkit-transform: translate3d(0, 0, 0); -moz- ...
- B. Fafa and the Gates
http://codeforces.com/problemset/problem/935/B Two neighboring kingdoms decided to build a wall betw ...
- ORP计
ORP计 ORP计通过测量铂或金电极与参比电极之间的电位差,转换成氧化还原电位信号.氧化还原电位测量用电极可与转换放大器组合,转换放大器部分与pH测量用相同.ORP计可用于排水处理(氰基处理.铬酸处理 ...
- 使用Python编写简单网络爬虫抓取视频下载资源
我第一次接触爬虫这东西是在今年的5月份,当时写了一个博客搜索引擎.所用到的爬虫也挺智能的,起码比电影来了这个站用到的爬虫水平高多了! 回到用Python写爬虫的话题. Python一直是我主要使用的脚 ...
- 升序排列的数组中是否存在A[i]=i
#include<stdio.h> void equal(int a[],int N) { int i; ;i<N;i++) { if(i<a[i]) { printf(&qu ...
- BFC (Block formatting context)
一:BFC 是什么 MDN解释: A block formatting context is a part of a visual CSS rendering of a Web page. ...
- mysql 系统用户最大文件打开数限制
纸上得来终觉浅,绝知此事多宕机...记录一下自己很蠢的一次故障处理过程. 上周的时候,一个刚上线的系统又开始反映登不上了,因为最近这个系统也老是出现这个问题,开发也一直在找问题中,所以也没太在意.于是 ...
- head 标签里有什么?
head 标签里有什么? 每一个 HTML 文档中,都有一个不可或缺的标签:<head> ,它作为一个容器,主要包含了用于描述 HTML 文档自身信息(元数据)的标签,这些标签一般不会在页 ...