RabbitMQ 官方NET教程(四)【路由选择】
在上一个教程中,我们构建了一个简单的日志记录系统。 我们能够广播日志消息给所有你的接收者。
在本教程中,我们将为其添加一个功能 - 我们将让日志接收者可以仅订阅一部分消息。 例如,我们将能够仅将关键的错误消息写入到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。
绑定(Bindings)
在以前的例子中,我们已经使用过绑定。类似下面的代码:
channel.QueueBind(queue: queueName,
exchange: "logs",
routingKey: "");
绑定表示转发器与队列之间的关系。我们也可以简单的认为:队列对该转发器上的消息感兴趣。
绑定可以附带一个额外的参数routingKey。 为了避免与BasicPublish
参数混淆,我们将其称为binding key
。 这就是我们如何用一个键创建一个绑定:
channel.QueueBind(queue: queueName,
exchange: "direct_logs",
routingKey: "black");
绑定键的意义依赖于转发器的类型。对于fanout类型,忽略此参数。
直接转发(Direct exchange)
我们从上一个教程的日志记录系统向所有消费者广播所有消息。 我们希望将其扩展为允许基于其严重性进行过滤日志消息。 例如,我们可能希望将日志消息写入磁盘的脚本仅接收严重错误,而不会在警告或信息日志消息上浪费磁盘空间。
我们正在使用一个fanout
的交换机,它不给我们很大的灵活性 - 它只能无意识地转发。
我们会使用direct
转发器。 direct
类型的转发器背后的路由算法很简单 - 消息传递到binding key
与消息的routing key
完全匹配的队列。
为了说明,请考虑以下设置:
在这个设置中,我们可以看到direct
类型的转发器X
与两个队列绑定。 第一个队列与绑定键orange
绑定,第二个队列与转发器间有两个绑定,一个与绑定键black
绑定,另一个与green
绑定键绑定。
在这样的设置中,发布附带一个选择键(routing key) orange
的消息至交换机,将被导向到队列Q1。 消息附带一个选择键 (routing key)black
或者green
将会被导向到Q2。 所有其他消息将被丢弃。
多重绑定(multiple bindings)
使用相同的绑定键绑定多个队列是完全合法的。 在我们的示例中,我们可以在X
和Q1
之间添加绑定键black
。 在这种情况下,direct
交换将表现得像fanout
,并将消息广播到所有匹配的队列。 附带选择键black
的消息将传送到Q1和Q2。
发送日志(Emittinglogs)
我们将此模型用于日志记录系统。我们将消息发送到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);
为了简化代码,我们假定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 类的代码:
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 > 0) ? args[0] : "info";
var message = (args.Length > 1)
? string.Join(" ", args.Skip( 1 ).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 < 1)
{
Console.Error.WriteLine("Usage: {0} [info] [warning] [error]",
Environment.GetCommandLineArgs()[0]);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
Environment.ExitCode = 1;
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
(而不是info
)保存到文件中,只需打开控制台并键入:
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
而且,例如,要发出error
日志消息,只需键入:
cd EmitLogDirect
dotnet run error "Run. Run. Or it will explode."
# => [x] Sent 'error':'Run. Run. Or it will explode.'
RabbitMQ 官方NET教程(四)【路由选择】的更多相关文章
- RabbitMQ 官方NET教程(五)【Topic】
在上一个教程中,我们改进了我们的日志记录系统.我们使用direct类型转发器,使得接收者有能力进行选择性的接收日志,,而非fanout那样,只能够无脑的转发 虽然使用direct类型改进了我们的系统, ...
- RabbitMQ 官方NET教程(六)【RPC】
在第二个教程中,我们学习了如何使用Work Queues在多个工作者之间分配耗时的任务. 但是如果我们需要在远程计算机上运行功能并等待结果怎么办? 那是一个不同的模式. 此模式通常称为远程过程调用或R ...
- RabbitMQ 官方NET教程(三)【发布/订阅】
上一篇博客中,我们实现了工作队列,并且我们的工作队列中的一个任务只会发给一个工作者,除非某个工作者未完成任务意外被杀死,会转发给另外的工作者.在这部分中,我们会做一些完全不同的事情 - 我们会向多个消 ...
- RabbitMQ 官方NET教程(二)【工作队列】
这篇中我们将会创建一个工作队列用来在工作者(consumer)间分发耗时任务. 工作队列的主要任务是:避免立刻执行资源密集型任务和避免必须等待其完成.相反地,我们进行任务调度:我们把任务封装为消息发送 ...
- RabbitMQ 官方NET教程(一)【介绍】
本教程假定RabbitMQ已在标准端口(5672)上的localhost上安装并运行.如果使用不同的主机,端口或凭据,连接设置将需要调整. RabbitMQ是一个消息代理:它接受并转发消息. 您可以将 ...
- struts2官方 中文教程 系列十四:主题Theme
介绍 当您使用一个Struts 2标签时,例如 <s:select ..../> 在您的web页面中,Struts 2框架会生成HTML,它会显示外观并控制select控件的布局.样式和 ...
- RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现)
RabbitMQ官方教程三 Publish/Subscribe(GOLANG语言实现) 在上一个教程中,我们创建了一个工作队列. 工作队列背后的假设是,每个任务都恰好交付给一个worker处理. 在这 ...
- RabbitMQ官方教程二 Work Queues(GOLANG语言实现)
RabbitMQ官方教程二 Work Queues(GOLANG语言实现) 在第一个教程中,我们编写了程序来发送和接收来自命名队列的消息. 在这一部分中,我们将创建一个工作队列,该队列将用于在多个wo ...
- RabbitMQ入门教程(四):工作队列(Work Queues)
原文:RabbitMQ入门教程(四):工作队列(Work Queues) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:/ ...
随机推荐
- zTree 模糊搜索
/** * 搜索树,高亮显示并展示[模糊匹配搜索条件的节点s] * @param treeId * @param searchConditionId 搜索条件Id */ function search ...
- html 报告页面 v1.2 批量数据生成表格
html 报告页面 v1.2 批量数据生成表格 上代码: <!DOCTYPE html> <html lang="en"> <head> < ...
- LNOI2019 退役记
Day -4 最近这两天智商有点不在线啊..得好好调整作息了,滚粗感++ 复习模板好啊 下午睡了一觉,智商似乎回来了一丢丢,滚粗感-- Day -3 智商略有回暖,滚粗感-- 明天有模拟赛,要加油啊 ...
- 【http反向代理】多个域名指向同一个ip的不同网站解决方法
一个服务器需要挂载多个项目[重点是都能通过域名访问] 实现原理: 1.当前市面上看到的一些服务器,开放的端口一般都要求为 '80' 端口 所以80端口成了商用端口 2.域名的绑定是绑定一个一般是绑定你 ...
- Linux系统学习之 一:新手必须掌握的Linux命令1
2018-10-03 16:04:12 一.常用系统工作命令 1.wget 命令 作用:用于在终端中下载网络文件. 格式:wget [参数] 下载地址 参数及作用: -b : 后台下载模式 -d:显示 ...
- Scrapy——5 下载中间件常用函数、scrapy怎么对接selenium、常用的Setting内置设置有哪些
Scrapy——5 下载中间件常用的函数 Scrapy怎样对接selenium 常用的setting内置设置 对接selenium实战 (Downloader Middleware)下载中间件常用函数 ...
- [POJ1226]Substrings(后缀数组)
传送门 给定 n 个字符串,求出现或反转后出现在每个字符串中的最长子串. 算法分析: 这题不同的地方在于要判断是否在反转后的字符串中出现.其实这并没有加大题目的难度. 只需要先将每个字符串都反过来写一 ...
- ASP.NET MVC 源码分析(一)
ASP.NET MVC 源码分析(一) 直接上图: 我们先来看Core的设计: 从项目结构来看,asp.net.mvc.core有以下目录: ActionConstraints:action限制相关 ...
- Java 和JS Base64加密
项目在登录.注册等场景实现时,经常会用到用户信息前端加密,然后项目后端二次解密,避免信息直接在浏览器上以明文显示. 本文主要介绍了base64加密的方式处理代码,不支持中文 源码如下: base64. ...
- RSA 数据加密和数字签名算法
PKCS8EncodedKeySpec pkcs8KeySpec = KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Pr ...