在上篇博文 译:3.RabbitMQ 之Publish/Subscribe(发布和订阅)  我们构建了一个简单的日志系统 我们能够向许多接收者广播日志消息。

在本篇博文中,我们将为其添加一个功能 - 我们将只能订阅一部分消息。 例如,我们只能将关键错误消息定向到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。

本文是译文,英文原文请移步:https://www.rabbitmq.com/tutorials/tutorial-four-java.html


Bindings 绑定

在前面的例子中,我们已经在创建绑定。您可能会记得以下代码:

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

绑定是交换和队列之间的关系。这可以简单地理解为:队列对来自此交换的消息感兴趣。

绑定可以采用额外的routingKey参数。为了避免与basic_publish参数混淆,我们将其称为 绑定密钥。这就是我们如何使用键创建绑定:

channel.queueBind(queueName,EXCHANGE_NAME,“black”);

绑定密钥的含义取决于交换类型。我们之前使用的 扇出交换只是忽略了它的价值。

Direct exchange 直接交换

我们上一个教程中的日志记录系统向所有消费者广播所有消息。我们希望扩展它以允许根据消息的严重性过滤消息。例如,我们可能需要一个程序将日志消息写入磁盘以仅接收严重错误,而不是在警告或信息日志消息上浪费磁盘空间。

我们使用的是扇出交换,它没有给我们太大的灵活性 - 它只能进行无意识的广播。

我们将使用直接交换。直接交换背后的路由算法很简单 - 消息进入队列,其 绑定密钥与消息的路由密钥完全匹配。

我们上一个教程中的日志记录系统向所有消费者广播所有消息。我们希望扩展它以允许根据消息的严重性过滤消息。例如,我们可能需要一个程序将日志消息写入磁盘以仅接收严重错误,而不是在警告或信息日志消息上浪费磁盘空间。

我们使用的是扇出交换,它没有给我们太大的灵活性 - 它只能进行无意识的广播。

我们将使用直接交换。直接交换背后的路由算法很简单 - 消息进入队列,其 绑定密钥与消息的路由密钥完全匹配。

为了说明这一点,请考虑以下设置:

在此设置中,我们可以看到直接交换X与两个绑定到它的队列。第一个队列绑定orange 绑定,第二个绑定有两个绑定,一个绑定密钥为black,另一个绑定为green。

在这样的设置中,使用路由密钥orange发布到交换机的消息 将被路由到队列Q1。路由键为black 或green的消息将转到Q2。所有其他消息将被丢弃。

Multiple bindings 多个绑定

使用相同的绑定密钥绑定多个队列是完全合法的。

在我们的例子中,我们可以在X和Q1之间添加绑定键黑色的绑定。

在这种情况下, direct 直接交换将表现得像 fanout一样,并将消息广播到所有匹配的队列。路由密钥为black的消息将传送到 Q1和Q2。

Emitting logs 发送日志

我们将此模型用于我们的日志系统。我们会将消息发送给直接交换,而不是扇出。

我们将提供日志严重性作为路由密钥。这样接收程序将能够选择它想要接收的严重性。

让我们首先关注发送日志。一如既往,我们需要先创建一个交换:

channel.exchangeDeclare(EXCHANGE_NAME, "direct");

我们已准备好发送消息:

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

为简化起见,我们假设“严重性”可以是“信息”,“警告”,“错误”之一。

Subscribing 订阅

接收消息将像上一个教程一样工作,但有一个例外 - 我们将为我们感兴趣的每个严重性创建一个新的绑定。

String queueName = channel.queueDeclare().getQueue();

for(String severity : argv){
channel.queueBind(queueName, EXCHANGE_NAME, severity);
}

Putting it all together 放到一起来看

EmitLogDirect.java:

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; public class EmitLogDirect {
private static final String EXCHANGE_NAME = "direct_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, BuiltinExchangeType.DIRECT); String severity = getSeverity(argv);
String message = getMessage(argv); channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + severity + "':'" + message + "'"); channel.close();
connection.close();
} private static String getSeverity(String[] strings) {
if (strings.length < 1)
return "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();
}
}

ReceiveLogsDirect.java

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 ReceiveLogsDirect {
private static final String EXCHANGE_NAME = "direct_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, BuiltinExchangeType.DIRECT);
String queueName = channel.queueDeclare().getQueue(); if (argv.length < 1) {
System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");
System.exit(1);
} for (String severity : argv) {
channel.queueBind(queueName, EXCHANGE_NAME, severity);
}
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);
}
}

译:4.RabbitMQ Java Client 之 Routing(路由)的更多相关文章

  1. 译:1. RabbitMQ Java Client 之 "Hello World"

    这些教程介绍了使用RabbitMQ创建消息传递应用程序的基础知识.您需要安装RabbitMQ服务器才能完成教程 1. 打造第一个Hello World 程序 RabbitMQ是一个消息代理:它接受和转 ...

  2. 译:5.RabbitMQ Java Client 之 Topics (主题)

    在 上篇博文 译:4.RabbitMQ 之Routing(路由) 中,我们改进了日志系统. 我们使用的是direct(直接交换),而不是使用只能进行虚拟广播的 fanout(扇出交换) ,并且有可能选 ...

  3. 译:6.RabbitMQ Java Client 之 Remote procedure call (RPC,远程过程调用)

    在  译:2. RabbitMQ 之Work Queues (工作队列)  我们学习了如何使用工作队列在多个工作人员之间分配耗时的任务. 但是如果我们需要在远程计算机上运行一个函数并等待结果呢?嗯,这 ...

  4. 译:3.RabbitMQ Java Client 之 Publish/Subscribe(发布和订阅)

    在上篇 RabbitMQ 之Work Queues (工作队列)教程中,我们创建了一个工作队列,工作队列背后的假设是每个任务都交付给一个工作者. 在这一部分,我们将做一些完全不同的事情 - 我们将向多 ...

  5. 译:2. RabbitMQ Java Client 之 Work Queues (工作队列)

    在上篇揭开RabbitMQ的神秘面纱一文中,我们编写了程序来发送和接收来自命名队列的消息. 本篇我们将创建一个工作队列,工作队列背后的假设是每个任务都交付给一个工作者 本篇是译文,英文原文请移步:ht ...

  6. 译: 4. RabbitMQ Spring AMQP 之 Routing 路由

    在上一个教程中,我们构建了一个简单的fanout(扇出)交换.我们能够向许多接收者广播消息. 在本教程中,我们将为其添加一个功能 - 我们将只能订阅一部分消息.例如,我们将只能将消息指向感兴趣的特定颜 ...

  7. 五、RabbitMQ Java Client基本使用详解

    Java Client的5.x版本系列需要JDK 8,用于编译和运行.在Android上,仅支持Android 7.0或更高版本.4.x版本系列支持7.0之前的JDK 6和Android版本. 加入R ...

  8. rabbitmq - java client lib一二事

    由于不可抗因素, 需要给对接方撸一个client的demo.基于比较老的jdk. 所幸找到了这里:http://www.rabbitmq.com/releases/rabbitmq-java-clie ...

  9. RabbitMQ的使用(五)RabbitMQ Java Client简单生产者、消费者代码示例

    pom文件: <dependencies> <dependency> <groupId>com.rabbitmq</groupId> <artif ...

随机推荐

  1. gitlab发送邮件

    1.修改配置文件,建议使用企业邮箱 #vim /etc/gitlab/gitlab.rb gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_a ...

  2. 51Nod 算法马拉松28 A题 先序遍历与后序遍历 分治

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - 51Nod1832 题意概括 对于给定的一个二叉树的先序遍历和后序遍历,输出有多少种满足条件的二叉树. 两棵二 ...

  3. 071 HBase的安装部署以及简单使用

    一:下载安装 1.下载安装 2.开启hadoop与zookeeper 3.修改配置文件hbase-env export JAVA_HOME=/opt/modules/jdk1.7.0_67 expor ...

  4. 如何查看Unity的版本

    打开Unity,Help->About Unity

  5. LoRaWAN 1.1 网络协议规范 - 2 LoRaWAN选项介绍

    LoRaWAN 1.1 网络协议规范 LoRaWAN 1.1 版本封稿很久了也没有完整啃过一遍,最近边啃边翻译,趁着这个机会把它码下来. 如果觉得哪里有问题,欢迎留言斧正. 翻译不易,转载请申明出处和 ...

  6. Nuxt.js 如何在 asyncData中 请求数据 ,并将拿到的数据传给子组件

    说明:同接口请求一样,也可以进行数据的处理:return  中 左侧的变量  可以直接拿到在页面上使用,也可以传递给子组件 下面再给出一段代码,方便觉得有用的.却又不想手敲的朋友们: async as ...

  7. Shiro笔记(二)身份验证

    Shiro笔记(二)身份验证 一.核心代码 @Test public void helloWorldTest(){ IniSecurityManagerFactory factory = new In ...

  8. 潭州课堂25班:Ph201805201 MySQL第三课 (课堂笔记)

    单表查询: select * from select sname from stu; 条件查询 select sname from stu where sid=2; select sname from ...

  9. [HihoCoder1398]网络流五·最大权闭合子图

    题目大意:有$N$项活动$M$个人,每个活动$act_i$有一个正的权值$a_i$,每个人$stu_i$有一个负的权值$b_i$.每项活动能够被完成当且仅当该项活动所需的所有人到场.如何选择活动使最终 ...

  10. WPF(C#)与MATLAB混合编程

    WPF(C#)与MATLAB混合编程 WPF可以为开发者提供便捷地构建用户交互界面的解决方法,而matlab则在科学计算方面有着无与伦比的优势,因此在一些需要将科学算法转换为应用软件的项目中,需要应用 ...