在之前的系统中,我们改进了我们的日志系统,我们使用direct 交换机代替fanout交换机,可以实现选择性的接受日志。

虽然使用direct 交换机改进了我们的系统,但是对于多种条件的判断,依然存在问题。如我们不仅仅想要根据日志的级别来订阅日志,同时也希望可以通过发出日志的源(即日志的生产者)来订阅。你也许已经通过unix 的工具syslog知道了这个概念,它同时通过级别(info/warn/crit...)和源(auth/cron/kern...).这种方式给了我们很大的灵活性--我们可以同时监听来自cron的critical 级别的错误消息和来自kern的所有消息。

为了在我们的系统中实现这种功能,我们需要学习更为复杂的交换机类型 --topic

Topic 交换机

发送到topic的交换机不能是任意routing_key,而必须是一系列使用"."。这些单词可以是任意的单子,单通常情况是是跟当前消息有关的一些功能,例如:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit".你可以指定任意多个字符,单上线是255字节。

绑定的key必须也是同样个格式,topic交换机背后的原理类似于把带有特定key的消息发送到所有跟这个key相匹配的队列上去,然而对于bindingKey这里有两个特殊的情况:

1:"*"可以代表一个单词(是单词不是字符--即"."分割的单词)

2:"?"可以代表0个或多个单词

例如:

在这个例子中,我们将要发送描述动物的消息,消息的routingkey将会有3部分组成,routingkey的第一个单词描述的是速度,第二个单词描述的是颜色,第三个单词是特殊描述: "<speed>.<colour>.<species>"。

我们创建了三个绑定,Q1使用bingingkey"*.orange.*",Q2使用"*.*.rabbit" 和"lazy.#"

绑定总结如下:

Q1所有的orange动物感兴趣

Q2想要所有的关于rabbits的消息,和所有的敢于layz动物的消息。

一个带有"quick.orange.rabbit"routingkey的消息会两个队列都接收,"lazy.orange.elephant"的消息同业也会被转发到两个队列上。而"quick.orange.fox"的消息仅仅进入Q1,"lazy.brown.fox"的消息只能被Q2接收。"lazy.pink.rabbit"的消息将再次被转发到Q2上,即使它匹配到了队列2的两个bingdingKey。"quick.brown.fox"的消息不会匹配到任何绑定,所有消息将会被忽略。

如果我们打破我们的约定发送带有4个单词的消息将会发生什么,例如"orange" 或者"quick.orange.male.rabbit"?答案是这些routingkey将不会匹配到任何的bingdingkey,因此将会被忽略

但是"lazy.orange.male.rabbit",因为匹配到了"lazy.#"bingdingkey,所有可以被Q2接收,即使其有4个单词。

Topic 交换机:Topic 交换机功能非常强大,可以完成像其他交换机那样工作。

当队列的bingdingkey使用"#" 时,它将会接收所有的消息,不论routingkey是什么--像fanout交换机那样

当特殊的"*"和"#"都没在bindingkey中使用时,它的行为就像direct交换机那样工作。

汇总

我没将要在我们的日志系统中使用"topic"交换机,我们将定我们的日志系统的routingkey有2个单词:"<facility>.<severity>"

代码和之前的案例基本上是一样的。

EmitLogTopic.cs:

using System;
using System.Linq;
using RabbitMQ.Client;
using System.Text; class EmitLogTopic
{
public static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "topic_logs",
type: "topic"); var routingKey = (args.Length > ) ? args[] : "anonymous.info";
var message = (args.Length > )
? string.Join(" ", args.Skip( ).ToArray())
: "Hello World!";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "topic_logs",
routingKey: routingKey,
basicProperties: null,
body: body);
Console.WriteLine(" [x] Sent '{0}':'{1}'", routingKey, message);
}
}
}

ReceiveLogsTopic.cs:

using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text; class ReceiveLogsTopic
{
public static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "topic_logs", type: "topic");
var queueName = channel.QueueDeclare().QueueName; if(args.Length < )
{
Console.Error.WriteLine("Usage: {0} [binding_key...]",
Environment.GetCommandLineArgs()[]);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
Environment.ExitCode = ;
return;
} foreach(var bindingKey in args)
{
channel.QueueBind(queue: queueName,
exchange: "topic_logs",
routingKey: bindingKey);
} Console.WriteLine(" [*] Waiting for messages. To exit press CTRL+C"); var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
var routingKey = ea.RoutingKey;
Console.WriteLine(" [x] Received '{0}':'{1}'",
routingKey,
message);
};
channel.BasicConsume(queue: queueName,
noAck: true,
consumer: consumer); Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
}

运行下面的案例:

接收所有的日志:

ReceiveLogsTopic.exe "#"

接收所有的"kern"源的日志:

ReceiveLogsTopic.exe "kern.*"

或者仅仅接受"critical"的日志:

ReceiveLogsTopic.exe "*.critical"

你可以创建多个绑定:

ReceiveLogsTopic.exe "kern.*" "*.critical"

发送一个routingkey是 "kern.critical"的消息

EmitLogTopic.exe "kern.critical" "A critical kernel error"

RabbitMQ 原文译05--Topics的更多相关文章

  1. RabbitMQ 原文译1.2--"Hello Word"

    本系列文章均来自官网原文,属于个人翻译,如有雷同,权当个人归档,忽喷. .NET/C# RabbitMQ 客户端下载地址:https://github.com/rabbitmq/rabbitmq-do ...

  2. RabbitMQ 原文译1.1--HelloWord

    本系列文章均来自官网原文,属于个人翻译,如有雷同,权当个人归档,忽喷. RabitMQ 是一个消息中间件,其实就是从消息生产者那里接受消息,然后发送给消息消费者.在这个传输过程中,可以定义一些缓存,持 ...

  3. RabbitMQ 原文译03--发布和订阅

    发布/订阅 在之前的案例中我们创建了一个工作队列,这个工作队列的实现思想就是一个把每一个任务平均分配给每一个执行者,在这个篇文章我们会做一些不一样的东西,把一个消息发送给多个消费者,这种模式就被称作& ...

  4. RabbitMQ 原文译02--工作队列

    工作队列: 在上一篇文章中我们我们创建程序发送和接受命名队列中的消息,在这篇文章我会创建一个工作队列,用来把耗时的操作分配给多个执行者. 工作队列(任务队列)的主要实现思想是避免马上执行资源密集型的任 ...

  5. RabbitMQ 原文译06--Remote procedure call(RPC)

    在第三篇文章中, 我们学习了怎么使用队列在多了消息消费者当中进行耗时任务轮询. 但是如果我们想要在远程电脑上运行一个方法,然后等待其执行结果,这就是一个不同的场景,这种就是我们一般讲的RPC(远程过程 ...

  6. RabbitMQ 原文译04--路由

    在前一篇文章中我们构建了一个简单的日志系统,我们可以向多个接受者广播消息. 在这篇文章我,我们将要添加一些功能使得针对部分消息的接受成为可能,例如我们只对错误的消息进行磁盘记录,同时又可以把所有的消息 ...

  7. RabbitMQ(五) -- topics

    RabbitMQ(五) -- topics `rabbitmq`中的`topic exchange`将路由键和某模式进行匹配,从而类似于正则匹配的方式去接收喜欢的信息. topic exchange ...

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

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

  9. [原创]Hadoop-2.5.2-HA原文译

    使用the Quorum Journal Manager实现HDFS高可用 2017/1/22 11:57:22 原文 目的(Purpose) * 这个指南提供了对HDFS-HA特性,使用QJM特性如 ...

随机推荐

  1. Memcached 两款.NET客户端的郁闷事儿

    不久以后就要负责一个比较大的项目,有多大?反正就是挺大的.现在处于筹备阶段,我主要负责系统框架搭建,在系统缓存这一块决定采用Http运行时缓存+memcached. memcached 以前用过几次 ...

  2. BrnShop开源网上商城第二讲:ASP.NET MVC框架

    在团队设计BrnShop的web项目之初,我们碰到了两个问题,第一个是数据的复用和传递,第二个是大mvc框架和小mvc框架的选择.下面我依次来说明下. 首先是数据的复用和传递:对于BrnShop的每一 ...

  3. 安装tcpreplay时报错:configure: error: libdnet not found

    安装tcpreplay时报错configure: error: libdnet not found 解决方法: 下载包libdnet-1.8.tar.gz并安装,依次执行: ./configure m ...

  4. C#学习:集合、迭代、泛型(1)

    一.System.Collections名称空间下几个接口表征着集合的功能: 1.IEnumerable:表征着迭代功能 public interface IEnumerable { IEnumera ...

  5. rx tx

  6. CMD-CMD命令之新建一个用户!

    1>>>>>> 新建管理员账号: net user net user xxxxx 123 /add net localgroup administrators xx ...

  7. NOI 1998 免费馅饼

    附题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=4901 时间限制(普通/Java ...

  8. UVA 557 - Burger(概率 递推)

     Burger  When Mr. and Mrs. Clinton's twin sons Ben and Bill had their tenth birthday, the party was ...

  9. ubuntu14.04如何卸载qq

    ubuntu安装了wine qq怎么去卸载呢?现在wine qq 比较好用的有ubuntukylin官网与deepin linux官网使用的deepin版本wine qq 2012国际版,还有Long ...

  10. ubuntu彻底卸载搜狗拼音输入法

    ubuntu彻底卸载搜狗拼音输入法,ubuntu安装搜狗输入法后如果觉得搜狗不是很适合自己,那应该怎么样彻底的卸载搜狗输入法呢?下面我们就来一步步彻底卸载掉搜狗输入法... 方法/步骤 1 找到安装的 ...