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类的代码:
using System;
using System.Linq;
using RabbitMQ.Client;
using System.Text; 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类的代码:
using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text; 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();
}
}
}
如果您只想将“警告”和“错误”(而不是“信息”)保存到文件中,只需打开控制台并键入:
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)(转载)
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
- RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)
(本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个任务会被交付给一个[工人].在这一部分我们将做一些完全不同的事情--我们将向 ...
- RabbitMQ系列教程之五:主题(Topic)
(本实例都是使用的Net的客户端,使用C#编写),说明,中文方括号[]表示名词. 在上一个教程中,我们改进了我们的日志记录系统. 没有使用只能够进行虚拟广播的[Fanout]交换机,而是使用了[D ...
随机推荐
- 关于开发微信小程序后端linux使用xampp配置https
关于开发微信小程序后端linux使用xampp配置https 背景 由于最近开发微信小程序,前后端交互需要使用https协议,故需要配置https服务 服务器环境 服务器系统 ubuntu 环境 xa ...
- 前端工程之npm
package.json是npm package的配置文件,存储当前项目相关的信息.如果下载npm中的包,包内会自带该文件.具体有如下属性: { "name" : "un ...
- js中new一个对象的过程
使用new关键字调用函数(new ClassA(-))的具体步骤: 1. 创建空对象{}: 2. 设置新对象的constructor属性为构造函数的名称,设置新对象的__proto__属性指向构造函数 ...
- 无阻塞加载和defer、async
无阻塞加载 把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载还是并行加载呢?在旧的浏览器下,都是按照先后顺序来加载的,这就保证了加载的js依赖不会发生问题.但是少部分新的浏览器已经开始允许 ...
- WCF(远程服务器返回错误: 400 错误的请求)
类似相关问题有以下: WCF- restful接口 POST方式调用报错(远程服务器返回错误: 400 错误的请求) WCF Rest:不使用UriTemplate使用post方式传参解决HTTP40 ...
- 线程机制、CLR线程池以及应用程序域
最近在总结多线程.CLR线程池以及TPL编程实践,重读一遍CLR via C#,比刚上班的时候收获还是很大的.还得要多读书,读好书,同时要多总结,多实践,把技术研究透,使用好. 话不多说,直接上博文吧 ...
- javascript基础-事件1
原理 事件分两种.第一种浏览器事件,由浏览器抛出事件,它是人机交互的基础:第二种自定义事件,由程序员抛出事件,它是模拟事件流程.两者都是为了完成数据的传递. 浏览器事件 机制 冒泡和捕获两种机制.因I ...
- JavaSE教程-01初识Java
1.计算机的概念 软件+硬件 2.操作系统 Windows.Mac.Linux.Unix等 3.计算机编程语言 计算机语言是一种人与计算机沟通的媒介. 分类: 机器语言:都是基于二进制的方式,由0和1 ...
- git上传本地项目到github
git软件下载地址:https://git-scm.com/download/ 1. 在GitHub上建立项目登录GitHub后,你可以在右边靠中那里找到一个按钮“New Repository”,点击 ...
- GPU编程--宏观理解篇(1)
GPU编程与CPU编程最大的不同可以概括为以下两点: "The same program is executed on many data elements in parallel" ...