这一篇我们将介绍如何订阅消息的一个子集。例如,我们只需要将日志中的error消息存储到日志文件中而将所有日志消息都在控制台打印出来。

绑定(Bindings)

在前面的例子中,我们创建了交换机和队列的绑定关系:

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

绑定交换机和队列可以理解为队列对这个交换机上的消息感兴趣。

绑定可以添加额外的参数routingKey,称之为绑定键(binding key)。下面是我们如何使用键创建绑定的方法:

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

绑定键的含义取决于交换类型。对于fanout类型而言,忽略这个参数。

直接交换(Direct exchange)

在前面的例子中,广播所有的消息到所有的消费者。这里,我们希望将它扩展为基于其严重性的过滤消息。例如,我们希望将重大错误信息写入磁盘,而不要浪费磁盘存储警告或消息类型的日志。

之前使用的fanout交换并没有给我们带来灵活性,它只能进行盲目地转发消息。

这边我们将使用直接交换。直接交换背后的算法很简单:消息将发送到绑定键与消息的路由键完全匹配的队列。

参考下面的图解:

我们可以看到,直接交换机x上绑定了两个队列。Q1队列与绑定键orange绑定,Q2队列与两个绑定键绑定,绑定键balck和绑定键green。

这样,附带orange绑定键的消息将会发送到Q1队列,附带black或green绑定键的消息会发送Q2队列,其他消息会丢弃。

多重绑定(Multiple bindings)

使用相同的绑定键绑定多个队列是完全合法的。如上图,一个附带了绑定键black的消息将会发送到Q1和Q2。这种情况下就成了特殊的fanout交换了。

发出日志(Emitting logs)

这里我们将使用direct交换,根据日志的严重性决定路由键。接收消息的程序根据消息的严重性接收。

首先,创建一个交换机:

channel.exchangeDeclare(EXCHANGE_NAME, "direct");

发送消息:

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

为了说明问题,假定严重性为:info,warning,error

订阅(Subscribing)

接收消息的方式基本和前面介绍过的一致,不同点在于我们将为每一个感兴趣的严重性创建绑定:

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

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

代码清单

发送端:

package com.xxyh.rabbitmq;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; import java.io.IOException;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeoutException; public class EmitLogDirect {
private static final String EXCHANGE_NAME = "direct_logs";
private static final String[] SEVERITIES = {"info", "warning", "error"}; public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT); // 发送10条消息
for (int i = 0; i < 10; i++) {
String severity = getSeverity();
String message = severity + "... log ..." + UUID.randomUUID().toString();
channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes("utf-8")); System.out.println(Thread.currentThread().getName()+" 发送消息:" + message);
} channel.close();
connection.close();
} // 随机产生一种消息类型
private static String getSeverity() {
Random random = new Random();
int i = random.nextInt(3);
return SEVERITIES[i];
}
}

接收端:

package com.xxyh.rabbitmq;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeoutException; public class ReceiveLogsDirect {
private static final String EXCHANGE_NAME = "direct_logs";
private static final String[] SEVERITIES = {"info", "warning", "error"}; public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel(); String queue = channel.queueDeclare().getQueue();
String severity = getSeverity(); channel.queueBind(queue, EXCHANGE_NAME, severity); final 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(Thread.currentThread().getName()+" 接收消息: " + message);
}
};
channel.basicConsume(queue, true, consumer); } // 随机产生一种消息类型
private static String getSeverity() {
Random random = new Random();
int i = random.nextInt(3);
return SEVERITIES[i];
}
}

多开启几个接收端,运气好的话,三个接收端分别收到三种类型的日志:

Recv1:

pool-1-thread-4 接收消息: error... log ...3f8faf78-12ca-45b6-91e3-7f6ac77912b5
pool-1-thread-4 接收消息: error... log ...d76d703a-af5a-412e-a534-b567ed94c743
pool-1-thread-5 接收消息: error... log ...8ac89111-5c6a-4c0f-a85d-31d1c66dcafd
pool-1-thread-6 接收消息: error... log ...c0054e75-5186-436b-8f19-033ccc725fcd
pool-1-thread-7 接收消息: error... log ...c2dc8196-6a11-4ea8-b02b-98eff0ff64a1

Recv2:

pool-1-thread-4 接收消息: warning... log ...8cc696ce-0b07-4223-bfc6-3be376fa3d7c
pool-1-thread-5 接收消息: warning... log ...579185f7-e09f-4bcf-81eb-85e35ebc9a5a
pool-1-thread-6 接收消息: warning... log ...38edb505-a944-4f64-8843-766dfca6a6ae

Recv3:

pool-1-thread-4 接收消息: info... log ...3e7ad3d4-dfd7-4f06-b4d7-bbe50ed0c9e6
pool-1-thread-5 接收消息: info... log ...5b9b3035-6b12-4c60-9907-ec8d8c7d21ba

Send:

main 发送消息:error... log ...3f8faf78-12ca-45b6-91e3-7f6ac77912b5
main 发送消息:error... log ...d76d703a-af5a-412e-a534-b567ed94c743
main 发送消息:warning... log ...8cc696ce-0b07-4223-bfc6-3be376fa3d7c
main 发送消息:info... log ...3e7ad3d4-dfd7-4f06-b4d7-bbe50ed0c9e6
main 发送消息:warning... log ...579185f7-e09f-4bcf-81eb-85e35ebc9a5a
main 发送消息:info... log ...5b9b3035-6b12-4c60-9907-ec8d8c7d21ba
main 发送消息:error... log ...8ac89111-5c6a-4c0f-a85d-31d1c66dcafd
main 发送消息:error... log ...c0054e75-5186-436b-8f19-033ccc725fcd
main 发送消息:error... log ...c2dc8196-6a11-4ea8-b02b-98eff0ff64a1
main 发送消息:warning... log ...38edb505-a944-4f64-8843-766dfca6a6ae

RabbitMQ入门(4)——路由(Routing)的更多相关文章

  1. RabbitMQ入门:路由(Routing)

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

  2. RabbitMQ入门教程——路由(Routing)

    绑定( Bindings)   之前的文章中我们已经创建过bindings,代码如下:         channel.QueueBind(queue: queueName, exchange: EX ...

  3. RabbitMQ入门:总结

    随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...

  4. RabbitMQ官方中文入门教程(PHP版) 第四部分:路由(Routing)

    路由(Routing) 在前面的教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重的错误日 ...

  5. RabbitMQ 入门教程(PHP版) 第四部分:路由(Routing)

    路由(Routing) 在前面的第三部分教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重 ...

  6. RabbitMQ学习总结 第五篇:路由Routing

    目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...

  7. RabbitMQ入门教程(六):路由选择Routing

    原文:RabbitMQ入门教程(六):路由选择Routing 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...

  8. RabbitMQ 入门系列:3、基础含义:持久化、排它性、自动删除、强制性、路由键。

    系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...

  9. 2.RABBITMQ 入门 - WINDOWS - 生产和消费消息 一个完整案例

    关于安装和配置,见上一篇 1.RABBITMQ 入门 - WINDOWS - 获取,安装,配置 公司有需求,要求使用winform开发这个东西(消息中间件),另外还要求开发一个日志中间件,但是也是要求 ...

随机推荐

  1. 并发编程 - io模型 - 总结

    1.提交任务得方式: 同步:提交完任务,等结果,执行下一个任务 异步:提交完,接着执行,异步 + 回调 异步不等结果,提交完任务,任务执行完后,会自动触发回调函数2.同步不等于阻塞: 阻塞:遇到io, ...

  2. Data striping

    条带化是把连续的数据分割成相同大小的数据块,把每段数据分别写入到阵列中的不同磁盘上的方法. 当多个进程同时访问一个磁盘时,可能会出现磁盘冲突.大多数磁盘系统都对访问次数(每秒的 I/O 操作,IOPS ...

  3. mytest3.py-api接入平台获取数据

    mytest3.py-api接入平台获取数据 import base64 import datetime import hashlib import urllib import urllib.pars ...

  4. linux 实用命令

    从一台机器远程连接到另一台机器: ssh platform@192.168.155.116 从一台机器发送文件到另一台机器: scp /home/weihuang/vie-zyzj.jar platf ...

  5. 八、网页版消息推送SDK-WebSockets

    介绍 由于项目组需求.最近在研究消息推送服务平台.结合业务和使用场景分析最终选择的是 Mosquitto 消息服务器. Mosquitto 服务器的安装.配置.集群搭建 我就不在这多说了.有兴趣的可以 ...

  6. 机器学习第2周---炼数成金-----线性回归与Logistic

    重点归纳 回归分析就是利用样本(已知数据),产生拟合方程,从而(对未知数据)迚行预测用途:预测,判别合理性例子:利用身高预测体重:利用广告费用预测商品销售额:等等.线性回归分析:一元线性:多元线性:广 ...

  7. python select poll

    http://www.cnblogs.com/coser/archive/2012/01/06/2315216.html

  8. SqlServer中创建Oracle链接服务器

    SqlServer中创建Oracle链接服务器 第一种:界面操作 (1)展开服务器对象-->链接服务器-->右击“新建链接服务器” (2)输入链接服务器的IP (3)链接成功后 第二种:语 ...

  9. PHP实现excel导出

    首先去下载PHPExcel类,地址http://phpexcel.codeplex.com/ 方法如下第一步引入这个扩展类 Vendor('PHPExcel'); 第二部就是方法了,下面简单的实现方法 ...

  10. JVM调优之Java进程消耗CPU过高

    JVM调优之Java进程消耗CPU过高 查找问题思路 1.查看cpu使用率,发现有线程cpu占用率很高  tops 咱们拿18092线程举例示范 2.查询pid对应的进程 ps -ef|grep 18 ...