RabbitMQ系列教程之四:路由(Routing)(转载)
(使用Net客户端)
在上一个教程中,我们构建了一个简单的日志系统,我们能够向许多消息接受者广播发送日志消息。
在本教程中,我们将为其添加一项功能 ,这个功能是我们将只订阅消息的一个子集成为可能。 例如,我们可以只将关键的错误消息输出到日志文件(以节省磁盘空间),同时仍然可以在控制台上打印所有日志消息。
1、绑定
在以前的例子中,我们已经创建了绑定。 你可能会记得如下代码:
channel.QueueBind(queue: queueName, exchange: "logs", routingKey: "");
【绑定】是【消息交换机】和【队列】之间的关系纽带,通过绑定把二者关联起来。 这可以简单地理解为:队列可以接收来自此【消息交换机】的消息。
【绑定】可以占用额外的路由选择参数。 为了避免与BasicPublish参数混淆,我们将其称为【绑定键】。 以下代码就是如何用一个键值来创建一个绑定:
channel.QueueBind(queue: queueName,
exchange: "direct_logs",
routingKey: "black");
【绑定键】的含义取决于交换类型。 以前我们使用的【Fanout】类型的【消息交换机】忽略了它的取值。
2、直接交换
在上一个教程中,我们的日志记录系统向所有【消费者】发送所有消息。 我们希望将其扩展为允许基于其严重性过滤消息。 例如,我们可能希望将写入磁盘日志消息的脚本仅接受严重错误,而不会在警告或信息日志消息上浪费磁盘空间。
我们正在使用一个【Fanout】类型的【消息交换机】,它不会给我们带来很大的灵活性 - 它只能无意识地发送。
我们将使用一个【Direct】类型的【消息交换机】。 直接转换路由的背后的算法其实是很简单的 - 把消息传递到【绑定键 binding key】和消息的【路由键 routing key】完全匹配的队列中。
为了说明,请考虑以下设置:

在这个设置中,我们可以看到【Direct】类型的【消息交换机】X与两个队列相绑定。 第一个队列与【绑定键】的值是Orange相绑定的,第二个队列有两个绑定,一个【绑定键】的值是black,另一个【绑定键】的值是green。
在这样的设置中,发布到具有【路由键】为orange的【消息交换机】的消息将被路由到队列Q1。 具有black或green【路由键】的消息将转到Q2。 所有其他消息将被丢弃。
3、多重绑定

使用相同的【绑定键】绑定多个队列是完全合法的。 在我们的示例中,我们可以在X和Q1之间添加【绑定键】是black的绑定。 在这种情况下,【direct】类型的【消息交换机】将表现得像【Fanout】类型的【消息交换机】,并将消息发送到所有匹配的队列。 具有【路由键】是black的消息将传送到Q1和Q2。
4、发出日志
我们将发送消息到【Direct】类型的【消息交换机】来替换【fanout】类型的【消息交换机】,在我们现在的日志系统将使用此模型。 我们将提供日志严重性作为【路由键】。 这样接收脚本就能够选择想要接收的严重性。 我们首先关注发出日志。
像以前一样,我们首先要建立一个【消息交换机】:
channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
现在,我们准备发送消息:
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "direct_logs",
routingKey: severity,
basicProperties: null,
body: body);
为了简化事情,我们假设“严重性”可以是“信息”,“警告”,“错误”之一。
5、订阅
接收消息将像上一个教程一样工作,除了一个例外 - 我们将为每个我们感兴趣的严重性创建一个新的绑定。

var queueName = channel.QueueDeclare().QueueName; foreach(var severity in args)
{
channel.QueueBind(queue: queueName,
exchange: "direct_logs",
routingKey: severity);
}

6、整合

以下是EmitLogDirect.cs类的代码:

1 using System;
2 using System.Linq;
3 using RabbitMQ.Client;
4 using System.Text;
5
6 class EmitLogDirect
7 {
8 public static void Main(string[] args)
9 {
10 var factory = new ConnectionFactory() { HostName = "localhost" };
11 using(var connection = factory.CreateConnection())
12 using(var channel = connection.CreateModel())
13 {
14 channel.ExchangeDeclare(exchange: "direct_logs",
15 type: "direct");
16
17 var severity = (args.Length > 0) ? args[0] : "info";
18 var message = (args.Length > 1)
19 ? string.Join(" ", args.Skip( 1 ).ToArray())
20 : "Hello World!";
21 var body = Encoding.UTF8.GetBytes(message);
22 channel.BasicPublish(exchange: "direct_logs",
23 routingKey: severity,
24 basicProperties: null,
25 body: body);
26 Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message);
27 }
28
29 Console.WriteLine(" Press [enter] to exit.");
30 Console.ReadLine();
31 }
32 }

以下是ReceiveLogsDirect.cs类的代码:

1 using System;
2 using RabbitMQ.Client;
3 using RabbitMQ.Client.Events;
4 using System.Text;
5
6 class ReceiveLogsDirect
7 {
8 public static void Main(string[] args)
9 {
10 var factory = new ConnectionFactory() { HostName = "localhost" };
11 using(var connection = factory.CreateConnection())
12 using(var channel = connection.CreateModel())
13 {
14 channel.ExchangeDeclare(exchange: "direct_logs",
15 type: "direct");
16 var queueName = channel.QueueDeclare().QueueName;
17
18 if(args.Length < 1)
19 {
20 Console.Error.WriteLine("Usage: {0} [info] [warning] [error]",
21 Environment.GetCommandLineArgs()[0]);
22 Console.WriteLine(" Press [enter] to exit.");
23 Console.ReadLine();
24 Environment.ExitCode = 1;
25 return;
26 }
27
28 foreach(var severity in args)
29 {
30 channel.QueueBind(queue: queueName,
31 exchange: "direct_logs",
32 routingKey: severity);
33 }
34
35 Console.WriteLine(" [*] Waiting for messages.");
36
37 var consumer = new EventingBasicConsumer(channel);
38 consumer.Received += (model, ea) =>
39 {
40 var body = ea.Body;
41 var message = Encoding.UTF8.GetString(body);
42 var routingKey = ea.RoutingKey;
43 Console.WriteLine(" [x] Received '{0}':'{1}'",
44 routingKey, message);
45 };
46 channel.BasicConsume(queue: queueName,
47 noAck: true,
48 consumer: consumer);
49
50 Console.WriteLine(" Press [enter] to exit.");
51 Console.ReadLine();
52 }
53 }
54 }

如果您只想将“警告”和“错误”(而不是“信息”)保存到文件中,只需打开控制台并键入:
cd ReceiveLogsDirect
dotnet run warning error > logs_from_rabbit.log
如果您想查看屏幕上的所有日志消息,请打开一个新终端,然后执行以下操作:
cd ReceiveLogsDirect
dotnet run info warning error
# => [*] Waiting for logs. To exit press CTRL+C
而且,例如,要发出错误日志消息,只需键入:
cd EmitLogDirect
dotnet run error "Run. Run. Or it will explode."
# => [x] Sent 'error':'Run. Run. Or it will explode.'
以下是原文地址:http://www.rabbitmq.com/tutorials/tutorial-four-dotnet.html
今天这篇文章终于翻译完了,整个系列还有几篇没翻译。英文水平有限,错误在所难免,欢迎大家提出来,共同学习。
RabbitMQ系列教程之四:路由(Routing)(转载)的更多相关文章
- RabbitMQ系列教程之四:路由(Routing)
(使用Net客户端)在上一个教程中,我们构建了一个简单的日志系统,我们能够向许多消息接受者广播发送日志消息.在本教程中,我们将为其添加一项功能 ,这个功能是我们将只订阅消息的一个子集成为可能. 例如, ...
- RabbitMQ系列教程之七:RabbitMQ的 C# 客户端 API 的简介(转载)
RabbitMQ系列教程之七:RabbitMQ的 C# 客户端 API 的简介 今天这篇博文是我翻译的RabbitMQ的最后一篇文章了,介绍一下RabbitMQ的C#开发的接口.好了,言归正传吧. N ...
- RabbitMQ系列教程之五:主题(Topic)(转载)
RabbitMQ系列教程之五:主题(Topic) (本实例都是使用的Net的客户端,使用C#编写),说明,中文方括号[]表示名词. 在上一个教程中,我们改进了我们的日志记录系统. 没有使用只能够进行虚 ...
- RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)(转载)
RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe) (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个 ...
- RabbitMQ系列教程之六:远程过程调用(RPC)(转载)
RabbitMQ系列教程之六:远程过程调用(RPC) 远程过程调用(Remote Proceddure call[RPC]) (本实例都是使用的Net的客户端,使用C#编写) 在第二个教程中,我们学习 ...
- RabbitMQ系列教程之一:我们从最简单的事情开始!Hello World(转载)
RabbitMQ系列教程之一:我们从最简单的事情开始!Hello World 一.简介 RabbitMQ是一个消息的代理器,用于接收和发送消息,你可以这样想,他就是一个邮局,当您把需要寄送的邮件投递到 ...
- 2.rabbitmq 系列教程
rabbitmq系列教程-文章[转] 视频分享: 链接:https://pan.baidu.com/s/1s_Qr2A1o0s8Ru0exK62jqg 提取码:eb68
- ASP.NET Identity系列教程(目录)转载
来源:http://www.cnblogs.com/r01cn/p/5179506.html 注:最近看到不少介绍微软ASP.NET Identity技术的文章,但感觉都不够完整深入,本人又恰好曾在A ...
- [转载]Windows网络编程系列教程之四:Select模型
原文:http://www.51see.com/asp/bbs/public/bp_show.asp?t_id=200308131152297103 讲一下套接字模式和套接字I/O模型的区别.先说明一 ...
随机推荐
- 安装npm报错 npm cache clean --force 搞定
- Linux下rz,sz与ssh的配合使用
Linux下rz,sz与ssh的配合使用 一般来说,linux服务器大多是通过ssh客户端来进行远程的登陆和管理的,使用ssh登陆linux主机以后,如何能够快速的和本地机器进行文件的交互呢,也就是上 ...
- CRM 2016 IFrame_A嵌入 EXT.net 页面 a.aspx,刷新另一IFrame_B嵌入 b.aspx gird.
说白了就是一个IFrame页面,执行另一IFrame页面的函数. a.aspx JS: parent.Xrm.Page.getControl("IFRAME_B").getObj ...
- JS一个算法题
题目:实现超出整数存储范围的两个大整数想加function(a,b).注意:参数a和b以及函数返回值都是字符串. 目的:考算法, 基本逻辑. 我实现的基本思路是: ①两个数字字符串长度补成一样,用字符 ...
- supervisor管理hive metastore和hive server2进程
1. hive_metastore.ini [program:hive_metastore] environment = JAVA_HOME=/usr/java/jdk1..0_172-amd64,H ...
- (转)CLR20R3 程序终止的几种解决方案
原文地址:https://blog.csdn.net/fxfeixue/article/details/4466899 这是因为.NET Framework 1.0 和 1.1 这两个版本对许多未处理 ...
- windows10配置python
官网下载:https://www.python.org python3---->Download Windows x86-64 executable installer python2----& ...
- Spqrk笔记
LSM:Least square method 最小二乘法 ALS:Alternating Least Squares 交替最小二乘法 http://blog.csdn.net/dreamer2020 ...
- 《linux性能及调优指南》 3.3 内存瓶颈
摘要:3.3内存瓶颈OnaLinuxsystem,manyprogramsrunatthesametime.Theseprogramssupportmultipleusers,andsomeproce ...
- python函数的return
return语句用于退出函数,向调用方返回一个表达式.return在不带参数的情况下(或者没有写return语句),默认返回None.None是一个特殊的值,它的数据类型是NoneType.NoneT ...