RabbitMQ之主题(Topic)【译】
在上一节中,我们改进了我们的日志系统,替换使用fanout exchange仅仅能广播消息,使得选择性的接收日志成为可能。
虽然使用direct exchange改进了我们的系统,但是它仍然由他的局限性,——不能根据多个条件来做路由。
在我们的日志系统,我们可能不仅仅想根据严重性来订阅日志,还可以根据其发出的日志源。你可能知道UNIX的系统日志工具,它同时根据严重性(info/warn/crit...)和来源(auth/cron/kern...)来路由日志。
这就给我们一个很大的灵活性——我们可能想接收来自“cron”的严重错误日志信息,和来自“kern”的所有日志信息。
为了实现在我们的日志系统,我们需要了解一写更复杂的topic exchange。
主题交换(Topic exchange)
发送到Topic exchange的消息不能携带有任何的routing-key——它必须是一个用点分隔的单词列表。这些词可以使任何东西,但是通常他们指定连接到消息的某些功能。
一些有效的routing key:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit"。可以是你定义的关于路由的任何词语,最多255个字节。
binding key也必须是相同的形式,topic exchange的背后逻辑和direct exchange一样——一个带有独特routing key的消息被发送到拥有相匹配的binding key的队列。然而,有两个特殊情况下的binding key:
"*"(星号)可以替代只有一个字。
“#”(井号)可以代替零个或多个字。
如下图所示:
在这个例子中,我们将要发送描述动物的消息,这个消息将要被带有三个词语的routing key来发送,在路由关键的第一个字将描述速度,第二个代表颜色和第三个代表特点:".."。
我们创建三个绑定,Q1的binding key是".orange.",Q2的binding key是"..rabbit" 和 "lazy.#".
这些绑定可以概括为:
Q1对所有橙色动物感兴趣。
Q2希望知道关于兔子的一切,和关于懒惰的动物。
Routing key 为"quick.orange.rabbit"的消息将会被分发到两个队列中,"lazy.orange.elephant"也会被分发到两个队列,另一方面"quick.orange.fox" 将只会分发到第一个队列,"lazy.brown.fox" 第二个,"lazy.pink.rabbit"也是只会发送到第二个队列一次,"quick.brown.fox"没有相匹配的,就会被丢弃。
如果我们打破我们的规定,发送一个字或者四个字的消息会怎样呢?例如"orange"和"quick.orange.male.rabbit"。那么这些消息将不会匹配任何绑定,并都将丢失。
主题交换
主题交换是强大的,他可以表现的像其他exchange一样。
当队列与“#”(井号)结合键绑定 - 它会接收所有邮件,而不考虑routing key - 就像fanout exchange。
当特殊字符“*”(星号)和“#”(井号)不使用的时候,该主题交换会表现得就像direct exchange一样。
代码整合(Putting it all together)
我们将在我们的日志系统中使用主题交换,我们假设日志的routing key有两个关键字"."。
EmitLogTopic.java
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 routingKey = getRouting(argv);
String message = getMessage(argv);
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
System.out.println(" [x] Sent '" + routingKey + "':'" + message + "'");
connection.close();
}
//...
}
ReceiveLogsTopic.java
import com.rabbitmq.client.*;
import java.io.IOException;
public class ReceiveLogsTopic {
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();
if (argv.length < 1) {
System.err.println("Usage: ReceiveLogsTopic [binding_key]...");
System.exit(1);
}
for (String bindingKey : argv) {
channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
}
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
}
};
channel.basicConsume(queueName, true, consumer);
}
}
原文地址:https://www.rabbitmq.com/tutorials/tutorial-five-java.html
代码地址:https://github.com/aheizi/hi-mq
相关:
1.RabbitMQ之HelloWorld
2.RabbitMQ之任务队列
3.RabbitMQ之发布订阅
4.RabbitMQ之路由(Routing)
5.RabbitMQ之主题(Topic)
6.RabbitMQ之远程过程调用(RPC)
RabbitMQ之主题(Topic)【译】的更多相关文章
- RabbitMQ之任务队列【译】
在第一个教程里面,我们写了一个程序从一个有名字的队列中发送和接收消息,在这里我们将要创建一个分发耗时任务给多个worker的任务队列. 任务队列核心思想就是避免执行一个资源密集型的任务,而程序要等待其 ...
- RabbitMQ之HelloWorld【译】
简介 RabbitMQ是一个消息代理,主要的想法很简单:它接收并转发消息.你可以把它当做一个邮局,当你发送邮件到邮筒,你相信邮差先生最终会将邮件投递给收件人.RabbitMQ在这个比喻里,是一个邮筒, ...
- 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 ).如 ...
- RabbitMQ入门(5)——主题(Topic)
前面我们介绍了通过使用direct exchage,改善了fanout exchange只能进行虚拟广播的方式.尽管如此,直接交换也有自身的局限,它不能基于多个条件路由. 在我们的日志系统中,也许我们 ...
- (转)RabbitMQ学习之主题topic(java)
http://blog.csdn.net/zhu_tianwei/article/details/40887775 参考:http://blog.csdn.NET/lmj623565791/artic ...
- 7.RabbitMQ系列之topic主题交换器
topic主题交换器它根据在队列绑定的路由键和路由模式通配符匹配将消息路由到队列. 生产者在消息头中添加路由键并将其发送到主题交换器. 收到消息后,exchange尝试将路由键与绑定到它的所有队列的绑 ...
- RABBITMQ/JAVA (主题)
上篇博文中,我们进一步改良了日志系统.即使用Direct类型的转换器,使得接受者有能力进行选择性的接收日志,而非fanout那样,只能够无脑的转发. 虽然使用Direct类型的转换器改进了日志系统.但 ...
- rabbitmq消息队列——"topic型交换器"
在之前的章节中我们改进了我们的日志系统,我们使用direct型交换器代替了只能盲目广播消息的fanout型交换器,这使得我们可以有选择性地接收日志. 尽管使用direct型交换器改进了我们的日志系统, ...
随机推荐
- 转:Sublime Text 2 实用快捷键[Mac OS X]
转: http://lucifr.com/2011/09/10/sublime-text-2-useful-shortcuts/ Sublime Text 2 实用快捷键[Mac OS X] luca ...
- 使用js的indexOf,lastIndexOf,slice三函数轻易得到url的服务器,路径和页名
js的indexOf,lastIndexOf,slice能帮我们在js字符串处理时少走一些弯路. 程序如下: var url="http://www.cnblogs.com/xiandeda ...
- Mac怎样改动开机password
Mac开机password忘了,咋办?开不开机啦 1.打开你的Mac,command +S 进入你的终端界面 2.输入/sbin/mount -uaw / 3.输入rm /var/db/.AppleS ...
- Google Maps API v2密钥申请以及实现地图定位导航
注意新建项目之前需要安装 google play services 然后导入 通过上图方法导入sdk包下面的一个包: \adt-bundle-windows-x86\sdk\extras\googl ...
- VMware 9.0.1安装Mac OS X Mountain Lion 10.8.2
原地址:http://zengwu3915.blog.163.com/blog/static/278348972013117114742496/ 所需软件1.VMware Workstation Bu ...
- ionic build android 失败 及 解决方案
原因:没有接受以下SDK组件的许可协议 解决方案: install Android Support Repository
- centos7 yum安装遇到报错:Head V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEYer
centos7 yum安装时遇到错误:Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY 无法安装时,可按如下方法解决: This mini ...
- Android体系架构详解
Andriod是什么? 首先,就像Android开源和兼容性技术负责人Dan Morrill在Android开发手册兼容性部分所解释的,“Android并不是传统的Linux风格的一个规范或分发版本, ...
- 关闭mysql慢查询日志
开启mysql慢日志 MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查 ...
- git eclipse 不标记修改后的文件(没有图标标明)
在使用Eclipse做开发的时候,已经修改了某个文件,但是文件的图标没有明显的标示,如图: 解决上面问题的办法如下: