RabbitMQ (五)主题(Topic)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37706355
上一篇博客中,我们进步改良了我们的日志系统。我们使用direct类型转发器,使得接收者有能力进行选择性的接收日志,,而非fanout那样,只能够无脑的转发,如果你还不了解:RabbitMQ
(四) 路由选择 (Routing)。
虽然使用direct类型改良了我们的系统,但是仍然存在一些局限性:它不能够基于多重条件进行路由选择。
在我们的日志系统中,我们有可能希望不仅根据日志的级别而且想根据日志的来源进行订阅。这个概念类似unix工具:syslog,它转发日志基于严重性(info/warning/crit…)和设备(auth/cron/kern…)
这样可能给我们更多的灵活性:我们可能只想订阅来自’cron’的致命错误日志,而不是来自’kern’的。
为了在我们的系统中实现上述的需求,我们需要学习稍微复杂的主题类型的转发器(topic exchange)。
1、 主题转发(Topic Exchange)
发往主题类型的转发器的消息不能随意的设置选择键(routing_key),必须是由点隔开的一系列的标识符组成。标识符可以是任何东西,但是一般都与消息的某些特性相关。一些合法的选择键的例子:"stock.usd.nyse", "nyse.vmw","quick.orange.rabbit".你可以定义任何数量的标识符,上限为255个字节。
绑定键和选择键的形式一样。主题类型的转发器背后的逻辑和直接类型的转发器很类似:一个附带特殊的选择键将会被转发到绑定键与之匹配的队列中。需要注意的是:关于绑定键有两种特殊的情况。
*可以匹配一个标识符。
#可以匹配0个或多个标识符。
2、 图解:
我们准备发送关于动物的消息。消息会附加一个选择键包含3个标识符(两个点隔开)。第一个标识符描述动物的速度,第二个标识符描述动物的颜色,第三个标识符描述动物的物种:<speed>.<color>.<species>。
我们创建3个绑定键:Q1与*.orange.*绑定Q2与*.*.rabbit和lazy.#绑定。
可以简单的认为:
Q1对所有的橙色动物感兴趣。
Q2想要知道关于兔子的一切以及关于懒洋洋的动物的一切。
一个附带quick.orange.rabbit的选择键的消息将会被转发到两个队列。附带lazy.orange.elephant的消息也会被转发到两个队列。另一方面quick.orange.fox只会被转发到Q1,lazy.brown.fox将会被转发到Q2。lazy.pink.rabbit虽然与两个绑定键匹配,但是也只会被转发到Q2一次。quick.brown.fox不能与任何绑定键匹配,所以会被丢弃。
如果我们违法我们的约定,发送一个或者四个标识符的选择键,类似:orange,quick.orange.male.rabbit,这些选择键不能与任何绑定键匹配,所以消息将会被丢弃。
另一方面,lazy.orange.male.rabbit,虽然是四个标识符,也可以与lazy.#匹配,从而转发至Q2。
注:主题类型的转发器非常强大,可以实现其他类型的转发器。
当一个队列与绑定键#绑定,将会收到所有的消息,类似fanout类型转发器。
当绑定键中不包含任何#与*时,类似direct类型转发器。
3、 完整的例子
发送端EmitLogTopic.java:
package com.zhy.rabbit._05_topic_exchange; import java.util.UUID; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class EmitLogTopic
{ private static final String EXCHANGE_NAME = "topic_logs"; public static void main(String[] argv) throws Exception
{
// 创建连接和频道
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, "topic"); String[] routing_keys = new String[] { "kernal.info", "cron.warning",
"auth.info", "kernel.critical" };
for (String routing_key : routing_keys)
{
String msg = UUID.randomUUID().toString();
channel.basicPublish(EXCHANGE_NAME, routing_key, null, msg
.getBytes());
System.out.println(" [x] Sent routingKey = "+routing_key+" ,msg = " + msg + ".");
} channel.close();
connection.close();
}
}
我们发送了4条消息,分别设置了不同的选择键。
接收端1,ReceiveLogsTopicForKernel.java
package com.zhy.rabbit._05_topic_exchange; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer; public class ReceiveLogsTopicForKernel
{ private static final String EXCHANGE_NAME = "topic_logs"; public static void main(String[] argv) throws Exception
{
// 创建连接和频道
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 声明转发器
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
// 随机生成一个队列
String queueName = channel.queueDeclare().getQueue(); //接收所有与kernel相关的消息
channel.queueBind(queueName, EXCHANGE_NAME, "kernel.*"); System.out.println(" [*] Waiting for messages about kernel. To exit press CTRL+C"); QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer); while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
String routingKey = delivery.getEnvelope().getRoutingKey(); System.out.println(" [x] Received routingKey = " + routingKey
+ ",msg = " + message + ".");
}
}
}
直接收和Kernel相关的日志消息。
接收端2,ReceiveLogsTopicForCritical.java
package com.zhy.rabbit._05_topic_exchange; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer; public class ReceiveLogsTopicForCritical
{ private static final String EXCHANGE_NAME = "topic_logs"; public static void main(String[] argv) throws Exception
{
// 创建连接和频道
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 声明转发器
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
// 随机生成一个队列
String queueName = channel.queueDeclare().getQueue(); // 接收所有与kernel相关的消息
channel.queueBind(queueName, EXCHANGE_NAME, "*.critical"); System.out
.println(" [*] Waiting for critical messages. To exit press CTRL+C"); QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer); while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
String routingKey = delivery.getEnvelope().getRoutingKey(); System.out.println(" [x] Received routingKey = " + routingKey
+ ",msg = " + message + ".");
}
}
}
只接收致命错误的日志消息。
运行结果:
[x] Sent routingKey = kernal.info ,msg = a7261f0d-18cc-4c85-ba80-5ecd9283dae7.
[x] Sent routingKey = cron.warning ,msg = 0c7e4484-66e0-4846-a869-a7a266e16281.
[x] Sent routingKey = auth.info ,msg = 3273f21f-6e6e-42f2-83df-1f2fafa7a19a.
[x] Sent routingKey = kernel.critical ,msg = f65d3e1a-0619-4f85-8b0d-59375380ecc9.
--------------------------------------------------------------------------------------------------------------------
[*] Waiting for messages about kernel. To exit press CTRL+C
[x] Received routingKey = kernel.critical,msg = f65d3e1a-0619-4f85-8b0d-59375380ecc9.
--------------------------------------------------------------------------------------------------------------------
[*] Waiting for critical messages. To exit press CTRL+C
[x] Received routingKey = kernel.critical,msg = f65d3e1a-0619-4f85-8b0d-59375380ecc9.
可以看到,我们通过使用topic类型的转发器,成功实现了多重条件选择的订阅。
RabbitMQ (五)主题(Topic)的更多相关文章
- RabbitMQ之主题(Topic)【译】
在上一节中,我们改进了我们的日志系统,替换使用fanout exchange仅仅能广播消息,使得选择性的接收日志成为可能. 虽然使用direct exchange改进了我们的系统,但是它仍然由他的局限 ...
- Windows Azure Service Bus (5) 主题(Topic) 使用VS2013开发Service Bus Topic
<Windows Azure Platform 系列文章目录> 项目文件,请在这里下载 在笔者之前的文章中Windows Azure Service Bus (1) 基础 介绍了Servi ...
- MQTT主题Topic讲解
文章转载于https://www.cnblogs.com/hayasi/p/7792191.html 我们已经把相关的连接报文搞定了.笔者想来想去还是决定先讲解一下订阅报文(SUBSCRIBE ).如 ...
- 【c#】RabbitMQ学习文档(五)Topic(主题。通配符模式)
(本实例都是使用的Net的客户端,使用C#编写),说明,中文方括号[]表示名词. 在上一个教程中,我们改进了我们的日志记录系统. 没有使用只能够进行虚拟广播的[Fanout]交换机,而是使用了[Dir ...
- RabbitMQ入门(5)——主题(Topic)
前面我们介绍了通过使用direct exchage,改善了fanout exchange只能进行虚拟广播的方式.尽管如此,直接交换也有自身的局限,它不能基于多个条件路由. 在我们的日志系统中,也许我们 ...
- RabbitMQ 官方NET教程(五)【Topic】
在上一个教程中,我们改进了我们的日志记录系统.我们使用direct类型转发器,使得接收者有能力进行选择性的接收日志,,而非fanout那样,只能够无脑的转发 虽然使用direct类型改进了我们的系统, ...
- (转)RabbitMQ学习之主题topic(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887775 参考:http://blog.csdn.NET/lmj623565791/artic ...
- RabbitMQ学习笔记(五) Topic
更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...
- Community Cloud零基础学习(五)Topic(主题)管理
我们以前讲过 Service Cloud 零基础(三)Knowledge浅谈,我们日常可以看见很多得文章或者帖子,我们可以将其通过data category / group进行管理.但是一个系统中得文 ...
- 7.RabbitMQ系列之topic主题交换器
topic主题交换器它根据在队列绑定的路由键和路由模式通配符匹配将消息路由到队列. 生产者在消息头中添加路由键并将其发送到主题交换器. 收到消息后,exchange尝试将路由键与绑定到它的所有队列的绑 ...
随机推荐
- SVN中更改连接用户
Eclipse中安装了SVN插件,当连接到SVN服务器后,便无法从客户端更改连接帐号 百度一下,也就知道 查看Eclipse中使用的是什么SVN Interface,位置在 windows > ...
- mybatis中autoCommit自动提交事务
今天学习了下mybatis, 对其中的autoCommit自动提交事务比较好奇, 研究了下,把配置和代码都放上 mapper.xml如下: <?xml version="1.0&quo ...
- 页面加载完之前显示Loading
1.第一种方式 HTML <body class="is-loading"> <div class="curtain"> <div ...
- 解决XMind运行卡顿
问题 XMind是一款很好用的脑图工具,它是基于eclipse开发的,而且基础功能是免费的.最近我安装了XMind 8 Pro,但是发现在Mac上运行有卡顿. 解决方式 解决这个问题的思路也很简单,软 ...
- windows下mongodb安装详解
1.打开官网https://www.mongodb.com/download-center?jmp=nav#community 注:这里小伙伴们可是开启下FQ软件psiphon 3下载(不开启FQ好像 ...
- Oracle12c中性能优化&功能增强新特性之临时undo
临时表最有意思的特点之一是undo段也存储在常规undo表空间中,而它们的undo反过来被redo保护,这会导致一些问题. 1) 写undo表空间需要数据库以读写模式打开,因此,只读数据库和物理备库 ...
- FFPLAY的原理(一)
概要 电影文件有很多基本的组成部分.首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置.AVI和Quicktime就 是容器的例子.接着,你有一组流,例如,你经常有的 ...
- py-oauth2包使用简记
接前两天线上项目py2升级py3的书,老廖的一个旧库snspy,他已经不维护了,用的api又比较久,不好升级,最后速度找了个OAuth库取代了它,由于时间紧张,直接在pypi上搜索了一下,找到这个支持 ...
- ruby1.9.2 +windowxp
ruby1.9.2 install on the window xp 1:在公司上網是有windows代理的(ntlm),而rails又都是gem安裝,對于接觸rails不多的人來時真是一場災難,我是 ...
- hadoop配置文件详解系列(二)-hdfs-site.xml篇
上一篇介绍了core-site.xml的配置,本篇继续介绍hdfs-site.xml的配置. 属性名称 属性值 描述 hadoop.hdfs.configuration.version 1 配置文件的 ...