在上一章中,我们构建了一个简单的日志系统,我们可以把消息广播给很多的消费者。在本章中我们将增加一个特性:我们可以订阅这些信息中的一些信息。例如,我们希望只将error级别的错误存储到硬盘中,同时可以将所有级别(error、info、warning等)的日志都打印在控制台上。

1、绑定(Bindings)

  在上一章中,我们已经创建了绑定关系,回顾一下代码:

1 channel.queueBind(queueName, EXCHANGE_NAME, "");

  一个绑定是一个交换器与队列之间的关系。意思是指:这个队列对这个交换器的消息感兴趣。

  该方法同时还有另一个routing Key参数,为了避免与basic_public参数产生中的路由键(routing key)混淆,我们称之为绑定键(bingind key),下面展示了如何通过一个绑定key创建一个绑定:

1 channel.queueBind(queueName, EXCHANGE_NAME, "black");

  注意,这个绑定键(这里是"black")的含义依赖于交换器的类型。比如在我们的日志系统中,交换器类型为fanout,此时,绑定键没有任何意义,会被忽略掉。

2、直连交换机(Direct Exchange)

  在我们之前的日志系统中,所有的消息被广播给所有的消费者,但是本章的需要是希望有一个程序可以只接收error级别的日志并保存到磁盘中,而不用浪费空间去存储那些info、warning级别的日志。

  我们正在用的广播模式的交换器并不够灵活,它只是不加思索地进行广播。因此,需要使用direct exchange来代替。直连交换器的路由算法非常简单:将消息推送到binding key与该消息的routing key相同的队列。

  为了说明这点,请看下图:

  

  在该图中,直连交换器X上绑定了两个队列。第一个队列绑定了绑定键orange,第二个队列有两个绑定键:black和green。在这种场景下,一个消息在布时指定了路由键为orange将会只被路由到队列Q1,路由键为black和green的消息都将被路由到队列Q2。其他的消息都将被丢失。

3、多重绑定

  

  同一个绑定键可以绑定到不同的队列上去,在上图中,我们也可以增加一个交换器X与队列Q2的绑定键,在这种情况下,直连交换器将会和广播交换器有着相同的行为,将消息推送到所有匹配的队列。一个路由键为black的消息将会同时被推送到队列Q1和Q2。

4、发送日志

  首先我们要一如既往地创建一个交换器:

1 channel.exchangeDeclare(EXCHANGE_NAME, "direct");

  并准备发送消息:

1 channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());

  我们需要确保在我们日志系统中参数"severity"是“info”、“warning”和“error”中的一个。

5、订阅

  创建接收消息与上一章基本相同,唯一不同的是,需要在创建绑定关系时,指定severity的值:

1 String queueName = channel.queueDeclare().getQueue();
2
3 for(String severity : argv){
4   channel.queueBind(queueName, EXCHANGE_NAME, severity);
5 }

6、完整的代码

  EmitLogDirect.java

 1 import com.rabbitmq.client.Channel;
 2 import com.rabbitmq.client.Connection;
 3 import com.rabbitmq.client.ConnectionFactory;
 4
 5 public class EmitLogDirect {
 6
 7   private static final String EXCHANGE_NAME = "direct_logs";
 8
 9   public static void main(String[] argv) throws Exception {
10     ConnectionFactory factory = new ConnectionFactory();
11     factory.setHost("localhost");
12     try (Connection connection = factory.newConnection();
13          Channel channel = connection.createChannel()) {
14         channel.exchangeDeclare(EXCHANGE_NAME, "direct");
15
16         String severity = getSeverity(argv);
17         String message = getMessage(argv);
18
19         channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes("UTF-8"));
20         System.out.println(" [x] Sent '" + severity + "':'" + message + "'");
21     }
22   }
23   //..
24 }

  ReceiveLogsDirect.java

 1 import com.rabbitmq.client.*;
 2
 3 public class ReceiveLogsDirect {
 4
 5   private static final String EXCHANGE_NAME = "direct_logs";
 6
 7   public static void main(String[] argv) throws Exception {
 8     ConnectionFactory factory = new ConnectionFactory();
 9     factory.setHost("localhost");
10     Connection connection = factory.newConnection();
11     Channel channel = connection.createChannel();
12
13     channel.exchangeDeclare(EXCHANGE_NAME, "direct");
14     String queueName = channel.queueDeclare().getQueue();
15
16     if (argv.length < 1) {
17         System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");
18         System.exit(1);
19     }
20
21     for (String severity : argv) {
22         channel.queueBind(queueName, EXCHANGE_NAME, severity);
23     }
24     System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
25
26     DeliverCallback deliverCallback = (consumerTag, delivery) -> {
27         String message = new String(delivery.getBody(), "UTF-8");
28         System.out.println(" [x] Received '" +
29             delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
30     };
31     channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { });
32   }
33 }

  为了测试方便,我们可以把"info"、"error"、"warning"都绑定到一个队列上去,然后生产者分别往"info"、"error"、"warning"发送消息:

  此时查看RabbitMq控制台:

  

  到此,发布-订阅涉及到的相关知识点都讲解完了,下一章将讲解Topic(主题模式)。

转载于:https://www.cnblogs.com/wuhenzhidu/p/10801103.html

RabbitMQ指南之四:路由(Routing)和直连交换机(Direct Exchange)相关推荐

  1. RabbitMQ入门:路由(Routing)

    在上一篇博客<RabbitMQ入门:发布/订阅(Publish/Subscribe)>中,我们认识了fanout类型的exchange,它是一种通过广播方式发送消息的路由器,所有和exch ...

  2. RabbitMQ的工作模式Routing 路由,test测试代

    RabbitMQ有以下几种工作模式 : 1.Work queues  工作队列 2.Publish/Subscribe 发布订阅 3.Routing      路由 4.Topics        通 ...

  3. HCNP路由交换学习指南--- 静态路由

    HCNP路由交换学习指南- 静态路由 文章目录 HCNP路由交换学习指南--- 静态路由 静态路由的基本概念 静态路由配置须知 默认路由 浮动静态路由 案例,静态路由和BFD联动 静态路由 Stati ...

  4. RabbitMQ指南(下)

    原文出处: Listen 在上一小节中我们改进了log系统,由于使用fanout类型的exchange只能进行全局的广播,因此我们使用direct类型的exchange做了代替, 使得我们可以选择性的 ...

  5. RabbitMQ指南(中)

    原文出处: Listen 在上一篇文章中,介绍了使用RabbitMQ的Hello World例子, 以及如何创建一个work queue.在work queue的例子中每条消息都只会被传递到一个wor ...

  6. java 路由_RabbitMQ入门:路由(Routing)

    在上一篇博客<RabbitMQ入门:发布/订阅(Publish/Subscribe)>中,我们认识了fanout类型的exchange,它是一种通过广播方式发送消息的路由器,所有和exch ...

  7. RabbitMq Direct exchange路由模型

    官网就是最好的文档 上一篇文章RabbitMq Publish/Subscribe消息发布订阅模式 消息发布订阅模式中,就是通过广播来实现分发的.所有的customer都能够收到全部的消息.实际业务场 ...

  8. RabbitMQ指南(三) 队列

    RabbitMQ指南(三) 队列 3.1 持久化 3.2 排他 3.3 自动删除 3.4 其他参数   声明队列使用的queueDeclare()方法包含一系列入参,这些入参定义了队列的属性.需要注意 ...

  9. erlang rebar 配置mysql_Erlang Rebar 使用指南之四:依赖管理

    Erlang Rebar 使用指南之四:依赖管理 全文目录: 本章链接: 1 rebar依赖定义 Rebar取得和构建符合OTP/Rebar规范的项目.如果项目包含子项目,Rebar会自动递归地构建它 ...

最新文章

  1. 结构体解决念数字问题
  2. OpenGL中的混合(Blending)
  3. Spring Boot 2.x基础教程:如何扩展XML格式的请求和响应
  4. 区块链3.0:侧链与跨链行业趋势报告|OK资本
  5. *CI框架装载器Loader.php源码分析
  6. 行内元素中去掉文字的上下间距,使得文字所在元素的高度同字体高度一致的方法...
  7. MySQL-MySQL数据类型及占用字节数
  8. 马斯克又一语双关 引用猫王金曲威胁直接向推特股东发要约收购?
  9. linux下用tcpdump抓包
  10. 为什么写了value属性 jq赋值value值不显示_[Go基础]理解 Go 标准库中的 atomic.Value 类型
  11. Object中Equals和ReferenceEquals不解之谜
  12. 个人漂浮装置UL安全标准 - 第 5 部分:浮力辅助设备(50 级) - 安全要求 UL 12402-5介绍
  13. mysql的语句大全_mysql语句大全
  14. 【转贴】从亚马逊公司的发展看电子商务
  15. php集成c sdk,GitHub - cuncle/spider-php-sdk
  16. POI使用模板制作PPT,替换内容时原样式丢失问题的解决办法
  17. Windows 下载WebStorm
  18. i3cpu驱动xp_Intel英特尔 Core i3/Core i5/Core i7系列CPU显示驱动 14.46.9.5394版 For XP-64
  19. Windows下MySQL8安装教程
  20. ubuntu16.04+ROS+科大讯飞+图灵AI机器人(四)——加入图灵机器人

热门文章

  1. 第5章 Python 数字图像处理(DIP) - 图像复原与重建10 - 空间滤波 - 统计排序滤波器 - 中值、最大值、最小值、中点、修正阿尔法均值滤波器
  2. springboot 关闭懒加载_SpringBoot新手入门篇
  3. 66319d电源使用说明书_矿用防爆交换机如何正确安装调试和使用?
  4. 黑马程序员_java基础笔记(15)...银行业务调度系统_编码思路及代码
  5. java-多线程操作全(Thread)-Timer简单使用
  6. Java-日期 正则表达式
  7. [USACO07NOV]牛继电器Cow Relays
  8. BootstrapVue UI组件
  9. iOS appstore分级
  10. ie11浏览器不能显示最新修改的程序,调试出现代码逻辑错误却依旧执行