RabbitMQ学习总结 第六篇:Topic类型的exchange
目录
RabbitMQ学习总结 第一篇:理论篇
RabbitMQ学习总结 第二篇:快速入门HelloWorld
RabbitMQ学习总结 第三篇:工作队列Work Queue
RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe
RabbitMQ学习总结 第六篇:Topic类型的exchange
RabbitMQ学习总结 第七篇:RCP(远程过程调用协议)
在上篇博文中,我们对之前的日志系统做了稍许的完善。没有使用fanout类型的exchange来广播,而是使用了direct类型的exchange来选择性的接收日志消息。
尽管使用了direct类型的exchange对日志系统有所提升,但还是有一些限制(消息不能够基于多重因素来路由)。
在我们的日志系统中,希望不仅仅能够根据日志级别来订阅,还可以根据指定的routing key来订阅。你应该可以理解的,就如unix的系统日志工具,日志消息路由规则不仅仅基于日志级别(info/warn/crit…),还可以基于设备(auth/cron/kern...)。
这样大大的提高的灵活性,例如我们可以只监听kern推送出来的error级别的日志。
为了在我们的日志记录系统中实现这样的功能,我们需要了解更多关于topic类型的exchange。
1、Topic类型的exchange
消息发送到topic类型的exchange上时不能随意指定routing_key(一定是指由一系列由点号连接单词的字符串,单词可以是任意的,但一般都会与消息或多或少的有些关联)。Routing key的长度不能超过255个字节。
Binding key也一定要是同样的方式。Topic类型的exchange就像一个直接的交换:一个由生产者指定了确定routing key的消息将会被推送给所有Binding key能与之匹配的消费者。然而这种绑定有两种特殊的情况:
- *(星号):可以(只能)匹配一个单词
- #(井号):可以匹配多个单词(或者零个)
下边来举个例子:

在这个例子中,我们将会发送一些描述动物的消息。Routing key的第一个单词是描述速度的,第二个单词是描述颜色的,第三个是描述物种的:“<speed>.<colour>.<species>”。
这里我们创建三个Binding:Binding key为”*.orange.*”的Q1,和binding key为”*.*.rabbit”和”lazy.#”的Q2。
这些binding可以总结为:
- Q1对所有橘色的(orange)的动物感兴趣;
- Q2希望能拿到所有兔子的(rabbit)信息,还有比较懒惰的(lazy.#)动物信息。
一条以” quick.orange.rabbit”为routing key的消息将会推送到Q1和Q2两个queue上,routing key为“lazy.orange.elephant”的消息同样会被推送到Q1和Q2上。但如果routing key为”quick.orange.fox”的话,消息只会被推送到Q1上;routing key为”lazy.brown.fox”的消息会被推送到Q2上,routing key为"lazy.pink.rabbit”的消息也会被推送到Q2上,但同一条消息只会被推送到Q2上一次。
如果在发送消息时所指定的exchange和routing key在消费者端没有对应的exchange和binding key与之绑定的话,那么这条消息将会被丢弃掉。例如:"orange"和"quick.orange.male.rabbit"。但是routing为”lazy.orange.male.rabbit”的消息,将会被推到Q2上。
Topic类型的exchange:
Topic类型的exchange是很强大的,也可以实现其它类型的exchange。
- 当一个队列被绑定为binding key为”#”时,它将会接收所有的消息,此时和fanout类型的exchange很像。
- 当binding key不包含”*”和”#”时,这时候就很像direct类型的exchange。
2、最终实现
我们准备在日志系统中使用topic类型的exchange。开始我们准备routing keys使用两个单词:"<facility>.<severity>"。代码和上篇博文里的差不多,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();
//指定一个topic类型的exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
//这里拿到routing key
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的代码:
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();
//指定一个topic类型的exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
String queueName = channel.queueDeclare().getQueue();
if (argv.length < ){
System.err.println("Usage: ReceiveLogsTopic [binding_key]...");
System.exit();
}
//绑定binding key
for(String bindingKey : argv){
channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
}
System.out.println(" [*] Waiting for 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 + "':'" + message + "'");
}
}
}
运行情况如下:

3、总结
在上边的基础上,只是丰富了routing key和binding key的写法。
参考链接:http://www.rabbitmq.com/tutorials/tutorial-five-java.html
RabbitMQ学习总结 第六篇:Topic类型的exchange的更多相关文章
- RabbitMQ学习总结 第三篇:工作队列Work Queue
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- RabbitMQ学习总结 第五篇:路由Routing
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
Redis总结(五)缓存雪崩和缓存穿透等问题 前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...
- 官网英文版学习——RabbitMQ学习笔记(七)Topic
在上一篇中使用直接交换器改进了我们的系统,使得它能够有选择的进行接收消息,但它仍然有局限性——它不能基于多个条件进行路由.本节我们就进行能够基于多个条件进行路由的topics exchange学习. ...
- RabbitMQ学习笔记(五) Topic
更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...
- Egret入门学习日记 --- 第六篇(书中 3.6~3.9节 内容)
第六篇(书中 3.6~3.9节 内容) 在本篇写之前,还是要为昨天写的日记道歉才行,差点就误人子弟了. 没想到在程序员界最低级的错误 “单词拼写错误” 还是会经常犯. childrenCreated ...
- RabbitMQ学习总结 第七篇:RCP(远程过程调用协议)
在http://www.cnblogs.com/leocook/p/mq_rabbitmq_2.html 这篇博文中我们实现了怎么去使用work queue来把比较耗时的任务分散给多个worker. ...
- 我们一起学习WCF 第六篇文件传输
原文 http://www.cnblogs.com/LipeiNet/p/4653830.html 前言:文件的输出我们并不陌生,但是今天我写的是用wcf模式进行文件传输,我觉得一大好处就是能进 ...
随机推荐
- hdu Random Sequence
这道题是道规律极强的题...真佩服在赛场上快速找到规律的人. d[i] a[i] res[i] 0 1.000000 C ...
- Css - 基础的css阴影效果
基本的css3阴影效果 width:971px; height:608px; border:1px solid #ccc; background-color:#fff; filter:progid:D ...
- Leetcode | Palindrome
Valid Palindrome Given a string, determine if it is a palindrome, considering only alphanumeric char ...
- HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- 2016.07.14,英语,《Vocabulary Builder》Unit 25
verb: comes from the Latin verbum, meaning 'word'. verbally: ['vɜːbəli] adv. 口头地,词句地, 逐字地 verbalize: ...
- (转)面试题--JAVA中静态块、静态变量加载顺序详解
public class Test { //1.第一步,准备加载类 public static void main(String[] args) { new Test(); //4.第四步,new一个 ...
- epoll 实际使用
void DataHandle::recv() { sleep(2); _data_router -> readInfoHw(&mInfo); ALOGD(SYS ...
- Web工程与RMI工程进行联调
1.首先导出RMI工程中的Service和entity类 到web工程中,以jar包的形式 public class ServiceManagerImpl { private static Servi ...
- java开发bug 在启动Tomcat 6.0时发现第一条信息便是
MyEclipse 8.5 + tomcat6 + jdk 1.8 启动的时候报错: The APR based Apache Tomcat Native library which allows o ...
- pro8
1.本次课学到的知识点 函数程序设计 结构化程序设计思想 程序解析 局部变量和全局变量 2.实验过程中遇到的问题及解决方法 实验过程中会遇到自定义函数的逻辑错误 与缺少定义变量 从主函数开始理清函数关 ...