RabbitMQ 之五 Topics
来源:互联网 发布:二手手机平台 知乎 编辑:程序博客网 时间:2024/06/08 06:21
在上篇文章Routing中,我们改进了日志系统,使用类型为direct的exchange,使得可以有选择性的接收日志。而不是fanout那样只是简单的广播信息。
虽然使用了direct的exchange来改进我们的日志系统,但是还是有局限性,无法根据多重条件来进行路由选择。
在我们的日志系统中,我们希望不仅仅根据日志的级别,而且根据日志的来源来订阅日志。类似于syslog这个unix工具,它根据严重性(info/warn/crit...)和设备(auth/cron/kern...)来选择发送日志。
这样可能给予我们更多的灵活性,我们希望关注来自于“cron”的critical errors和来自于“kern”的所有日志。
发往topic类型exchange的消息不能任意选择routing_key,必须是由.隔开的一系列标识,这些标识可以是任何东西,但经常是一些与消息特性相关的词,一些合法的routing key的例子:"stock.usd.nyse","nyse.vmw","quick.orange.rabbit"。routing key的长度限制为255bytes。
绑定的key和routing key的形式一样,topic exchange的逻辑跟direct exchange类似。附带特殊routing key的消息会被分发到所有绑定匹配的binding key的queue中。需要注意的是,关于binding key有两个特殊的情况。
* 可以匹配一个标识。
#可以匹配0个或多个标识。
如上图所示,我们准备发送关于动物的消息,消息会附带一个routing key包含3个标识(两个.隔开),第一个标识描述速度,第二个标识描述颜色,第三个标识描述种类:"<speed>.<colour>.<species>"。
我们建了3个绑定关系。Q1通过"*.orange.*"绑定,Q2通过"*.*.rabbit"和"lazy.#"来绑定。
这几个绑定关系可以总结为:
Q1对所有橙色动物感兴趣。
Q2想要知道关于兔子的一切以及关于懒洋洋的动物的一切
消息附带routing key为"quick.orange.rabbit"将会被分发到Q1和Q2。消息附带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,虽然这个消息匹配到两个binding key。消息附带routing key为"quick.brown.fox"将会被丢弃。
如果我们违法我们的约定,发送一个或者四个标识符的选择键,类似:orange,quick.orange.male.rabbit,这些选择键不能与任何绑定键匹配,所以消息将会被丢弃。
代码如下:EmitLogTopic.java
package org.rabbitmq;import com.rabbitmq.client.BuiltinExchangeType;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) {Connection connection = null;Channel channel = null;try {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");factory.setPort(5673);connection = factory.newConnection();channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);String regArgv[] = new String[]{"kern.critical","A critical kernel error"};String routingKey = getRouting(regArgv);String message = getMessage(regArgv);channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes("UTF-8"));System.out.println(" [x] Sent '" + routingKey + "':'" + message + "'");} catch (Exception e) {e.printStackTrace();} finally {if (connection != null) {try {connection.close();} catch (Exception ignore) {}}}}private static String getRouting(String[] strings) {if (strings.length < 1)return "anonymous.info";return strings[0];}private static String getMessage(String[] strings) {if (strings.length < 2)return "Hello World!";return joinStrings(strings, " ", 1);}private static String joinStrings(String[] strings, String delimiter, int startIndex) {int length = strings.length;if (length == 0)return "";if (length < startIndex)return "";StringBuilder words = new StringBuilder(strings[startIndex]);for (int i = startIndex + 1; i < length; i++) {words.append(delimiter).append(strings[i]);}return words.toString();}}ReceiveLogsTopic.java
package org.rabbitmq;import java.io.IOException;import com.rabbitmq.client.AMQP;import com.rabbitmq.client.BuiltinExchangeType;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.Consumer;import com.rabbitmq.client.DefaultConsumer;import com.rabbitmq.client.Envelope;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");factory.setPort(5673);Connection connection = factory.newConnection();Channel channel = connection.createChannel();channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);String queueName = channel.queueDeclare().getQueue();String regArgv[] = new String[]{"kern.*","*.critical"};if (regArgv.length < 1) {System.err.println("Usage: ReceiveLogsTopic [binding_key]...");System.exit(1);}for (String bindingKey : regArgv) {channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);}System.out.println(" [*] Waiting for messages. To exit press CTRL+C");Consumer consumer = new DefaultConsumer(channel) {@Overridepublic 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);}}
运行结果如下:
参考:http://www.rabbitmq.com/tutorials/tutorial-five-java.html
- RabbitMQ 之五 Topics
- RabbitMq之Routing,Topics
- RabbitMQ之Topics
- RabbitMQ学习(五).NET Client之Topics
- RabbitMQ官方文档翻译之Topics(五)
- python系列之 RabbitMQ -- TOPICS
- Rabbitmq教程翻译(五)Topics主题
- RabbitMQ 学习笔记(五):Topics
- RabbitMQ Topics
- RabbitMQ学习小结(五)—— Topics[Python]
- rabbitmq学习5:Topics
- rabbitmq学习5:Topics
- RabbitMQ java Topics主题
- rabbitmq学习5:Topics
- 七、rabbitMQ Topics
- RabbitMQ学习笔记六:话题(Topics)
- RabbitMQ入门教程(七):主题交换机Topics
- RabbitMQ案例五之Routing路由功能
- Storm基本概念
- java-String(二)
- CSDN积分排名规则
- 先码后看 Tomcat是怎么启动容器的——Digester篇 侵立删
- 搭建适用于Ubuntu/CentOS的IKEV2/L2TP的VPN
- RabbitMQ 之五 Topics
- 内存知识梳理 3. Bootmem机制
- Access restriction required library rt.jar
- ZTspringMVC 几种页面跳转方式
- 希尔排序
- 内部类的理解以及扩展
- Android 蓝牙开发【五】OPP接收文件
- 给运行的Python程序添加参数
- React生命周期