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型交换器改进了我们的日志系统, ...
随机推荐
- 安装Was liberty之步骤
安装文件下载:http://pan.baidu.com/s/1dDl8PuL 安装三大步骤:拷贝文件,安装VNC和安装WasLiberty 拷贝文件是将需要的文件InstalMgr1.6.2_LNX_ ...
- 【iOS开发-59】LOL案例:单组tabView、alertView样式、实现监听,以及用reloadData数据刷新
案例效果: (1)先在storyboard中拖拽出一个tableView,然后下面用代码. --tableView继承自scrollView.所以自然有滚动的特性 --最基本的还是数据转模型.以及对c ...
- 用thinkphp连接mysql数据库
一.设置mysql数据库的参数 thinkphp\Application\Home\Conf\config.php <?php return array( //'配置项'=>'配置值' ' ...
- ASP.NET MVC中权限控制的简单实现
1.重写AuthorizeAttribute类,用自己的权限控制逻辑重写AuthorizeCore方法 public class MyAuthorizeAttribute : AuthorizeAtt ...
- Minimum edit distance(levenshtein distance)(最小编辑距离)初探
最小编辑距离的定义:编辑距离(Edit Distance),又称Levenshtein距离.是指两个字串之间,由一个转成还有一个所需的最少编辑操作次数.许可的编辑操作包含将一个字符替换成还有一个字符. ...
- QtGui.QFileDialog
The QtGui.QFileDialog is a dialog that allows users to select files or directories. The files can be ...
- Android EditText禁止复制粘贴
1,自定义EditText package com.example.ui; import android.annotation.SuppressLint; import android.content ...
- sql通过某个字段名找到数据库中对应的表
sql通过某个字段名找到数据库中对应的表 SELECT sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name= ...
- 【Linux】mkdir命令
用途 mkdir命令主要是用来建立目录的 全称 mkdir的全称为:Make Directory 参数 -m :配置文件的权限 -p :帮助你直接将所需要的目录递归建立起来 案例 进入到目录/usr/ ...
- 17-spring学习-AOP初步实现
AOP是面向方面的编程,在实际开发中,AOP都会工作在业务层,因为业务层要调用数据层,而业务层也要完成所有辅助性的业务层操作. 范例:定义业务层操作接口: package com.Spring.Ser ...