RabbitMQ 原文译04--路由
在前一篇文章中我们构建了一个简单的日志系统,我们可以向多个接受者广播消息。
在这篇文章我,我们将要添加一些功能使得针对部分消息的接受成为可能,例如我们只对错误的消息进行磁盘记录,同时又可以把所有的消息打印到屏幕上。
绑定
在之前的案例中,我们已经创建了一个绑定,可以重新调用如下的代码:
channel.QueueBind(queue: queueName,exchange: "logs",routingKey: "");
绑定是交换机和队列之间的关系,可以简单的理解为队列对该交换机上的消息感兴趣。
绑定可以设定参数routingKey,为了避免和BasicPublish 方法的参数混淆,我们暂且称之为binding key,下面是我们创建一个带有指定binding key的绑定:
channel.QueueBind(queue: queueName,exchange: "direct_logs",routingKey: "black");
Direct exchange
我们之前的日志系统,把接受到的消息广播给所有的接受者,我们将要扩展它使得其能够根据消息的级别来过滤发送消息,例如我们想让记录日志的接受者仅仅接受严重性级别的错误消息,而不用在警告和信息级别的消息上浪费磁盘空间。
fanout没有办法提供给我们这样的灵活性,它只能对接受到的消息进行直接广播,而不去关心 routing key.
这里我们使用direct类型的交换机去代替,direct类型的交换机的实现思想非常简单--消息将会被发送到其Binding key 和消息的routing key 完全匹配的队列上。
为了说明这个问题,考虑下面的设定:
在这个交换机上绑定了两个队列,第一个队列绑定的bingding key 为"orange",第二个队列绑定了两个binding key,一个是"black",另外一个是"green",在这样的配置下,如果一个带有routing key为"orange"的消息,竟会被路由到队列Q1上,而带有routing key为"black" 或 "green"的消息将会被路由到队列Q2上。
多绑定
使用一个routing key 绑定多个队列完全是合法的,在我们案例中我们可以在 路由X 和 队列Q1,Q2中同时添加一个binding key为"black"的绑定,在这种情况下路由 X 将会像 fanout交换机一样帮匹配到的消息发送给所有的接受者:路由会把routing key 为"black"的消息发送给Q1和Q2。
嵌入日志
我们使用这种模式来构建我们的日志系统,代替fanout我们将会把我们的消息发送到direct类型的交换机,我们把日志级别作为路由的rouing key,这样接受者就可以根据日志级别选择接受其感兴趣的日志。
像往常一样,首先我们需要创建一个交换机:
channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
然后我们准备发送消息:
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "direct_logs",routingKey: severity,basicProperties: null, body: body);
我们简单的假设 severity 分为以下几种:"info","warning","error".
订阅
接受消息和之前的一样,唯一的区别就是我们将会为我们感兴趣的每一个级别的消息新建绑定:
var queueName = channel.QueueDeclare().QueueName; foreach(var severity in args)
{
channel.QueueBind(queue: queueName,exchange: "direct_logs",routingKey: severity);
}
汇总
EmitLogDirect.cs:
class EmitLogDirect
{
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: "direct_logs",
type: "direct"); var severity = (args.Length > ) ? args[] : "info";
var message = (args.Length > )
? string.Join(" ", args.Skip( ).ToArray())
: "Hello World!";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "direct_logs",
routingKey: severity,
basicProperties: null,
body: body);
Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message);
} Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
ReceiveLogsDirect.cs:
class ReceiveLogsDirect
{
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: "direct_logs",
type: "direct");
var queueName = channel.QueueDeclare().QueueName; if(args.Length < )
{
Console.Error.WriteLine("Usage: {0} [info] [warning] [error]",
Environment.GetCommandLineArgs()[]);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
Environment.ExitCode = ;
return;
} foreach(var severity in args)
{
channel.QueueBind(queue: queueName,
exchange: "direct_logs",
routingKey: severity);
} Console.WriteLine(" [*] Waiting for messages."); 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();
}
}
}
编译执行代码:
例如:如果你仅仅想保存"warning"和"error"的消息,打开控制台输入:ReceiveLogsDirect.exe warning error
发送一个Error消息, 控制台输入 EmitLogDirect.exe error "Run. Run. Or it will explode."
RabbitMQ 原文译04--路由的更多相关文章
- RabbitMQ 原文译1.2--"Hello Word"
本系列文章均来自官网原文,属于个人翻译,如有雷同,权当个人归档,忽喷. .NET/C# RabbitMQ 客户端下载地址:https://github.com/rabbitmq/rabbitmq-do ...
- RabbitMQ 原文译1.1--HelloWord
本系列文章均来自官网原文,属于个人翻译,如有雷同,权当个人归档,忽喷. RabitMQ 是一个消息中间件,其实就是从消息生产者那里接受消息,然后发送给消息消费者.在这个传输过程中,可以定义一些缓存,持 ...
- RabbitMQ 原文译03--发布和订阅
发布/订阅 在之前的案例中我们创建了一个工作队列,这个工作队列的实现思想就是一个把每一个任务平均分配给每一个执行者,在这个篇文章我们会做一些不一样的东西,把一个消息发送给多个消费者,这种模式就被称作& ...
- RabbitMQ 原文译02--工作队列
工作队列: 在上一篇文章中我们我们创建程序发送和接受命名队列中的消息,在这篇文章我会创建一个工作队列,用来把耗时的操作分配给多个执行者. 工作队列(任务队列)的主要实现思想是避免马上执行资源密集型的任 ...
- RabbitMQ 原文译06--Remote procedure call(RPC)
在第三篇文章中, 我们学习了怎么使用队列在多了消息消费者当中进行耗时任务轮询. 但是如果我们想要在远程电脑上运行一个方法,然后等待其执行结果,这就是一个不同的场景,这种就是我们一般讲的RPC(远程过程 ...
- RabbitMQ 原文译05--Topics
在之前的系统中,我们改进了我们的日志系统,我们使用direct 交换机代替fanout交换机,可以实现选择性的接受日志. 虽然使用direct 交换机改进了我们的系统,但是对于多种条件的判断,依然存在 ...
- RabbitMQ六种队列模式-路由模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主 ...
- [译]RabbitMQ教程C#版 - 路由
先决条件 本教程假定 RabbitMQ 已经安装,并运行在localhost标准端口(5672).如果你使用不同的主机.端口或证书,则需要调整连接设置. 从哪里获得帮助 如果您在阅读本教程时遇到困难, ...
- RabbitMQ的工作队列和路由
工作队列:Working Queue 工作队列这个概念与简单的发送/接收消息的区别就是:接收方接收到消息后,可能需要花费更长的时间来处理消息,这个过程就叫一个Work/Task. 几个概念 分 ...
随机推荐
- linux tar打包
范例一:将整个 /etc 目录下的文件全部打包成为 /tmp/etc.tar[root@linux ~]# tar -cvf /tmp/etc.tar /etc <==仅打包,不压缩![root ...
- HDU-4604 Deque DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604 因为deque最后的数列是单调不降的,因此,我们可以枚举数列中的某个中间数Ai,如果从中间数Ai ...
- windows 2003 插金税盘 可以识别, 但是会蓝屏重启
- linux之C编程实战小例
人生匆匆一趟,打不打酱油?怎么打?怎么打"质量好点的酱油"?由你决定.打酱油是一种态度,更是一种生活! 哈哈,事不关己不开口,专心一意打酱油! 请记住下面些许话: 不要一味的说别人 ...
- Android实例-如何将文件打包到安装文件(XE8+小米2)
结果: 1.文件名支持英文字母.数字,不支持中文,大小写敏感. 2.文件最好放在根目录下,或是子目录下,如果放在根目外,根目录改名后,找不到文件. 3.打开Project->Deployment ...
- mac linux netstat -n
一直都不明白为什么mac就是不现实8080端口,现在明白了 USERtekiiMac-3:~ user$ netstat -an | grep tcp46 tcp46 0 0 *.8009 *.* L ...
- JBOss 端口没占用!
打开exlipse ,启动服务器 后,报如下错误:
- 文件上传(FileUpload控件)
asp.net 文件上传,大文件上传. 新建一个asp.net页面,在工具栏里拖入 FileUpload 上传控件.一个按钮 Button ! ! ! 进入Button事件 //- ...
- (原创)vagrant up 异常报错,出现 There was an error while executing `VBoxManage` 的解决方法
最近在使用 vagrant homestead 时,不小心在虚拟机上使用了 exit 命令退出虚拟机,导致再使用 vagrant up 时出现以下错误: Bringing machine 'larav ...
- 【Stage3D学习笔记续】山寨Starling(十一):Touch事件体系
我们的山寨Starling版本将会在这里停止更新了,主要还是由于时间比较有限,而且我们的山寨版本也很好的完成了他的任务“了解Starling的核心渲染”,接下来的Starling解析我们将会直接阅读S ...