咨询热线:18578863303 联系人:王春艳 地址:博山区域城镇张博附线(205国道)与华城路路口向北200米路西
[译]RabbitMQ教程C#版 - 主题
来源:易利go! | 登入口 发布时间:2019-06-26 点击量:346
先决条件本教程假定RabbitMQ已经安装,并运行在localhost
标准端口(5672)。如果你使用不同的主机、端口或证书,则需要调整连接设置。
从哪里获得帮助如果您在阅读本教程时遇到困难,可以通过邮件列表 联系我们。
主题
(使用.NET客户端)
在 教程[4] 中,我们改进了我们日志系统。我们用direct
交换器替换了只能呆滞广播消息的fanout
交换器,从而可以有选择性的接收日志。
虽然使用direct
交换器改进了我们的系统,但它仍然有局限性 - 不能基于多个标准进行路由。
在我们的日志系统中,我们可能不仅要根据日志的严重性订阅日志,可能还要根据日志分发源来订阅日志。或许您可能从 unix syslog 工具中了解过这种概念,syslog 工具在路由日志的时候是可以既基于严重性(info/warn/crit...)又基于设备(auth/cron/kern...)的。
这种机制会给我们带来极大的灵活性 - 我们可以仅监听来自cron
的关键错误日志,与此同时,监听来自kern
的所有日志。
要在我们的日志系统中实现这一特性,我们需要学习更复杂的topic
交换器。
Topic交换器
发送到topic
交换器的消息不能随意指定routing key
,它必须是一个由点分割的单词列表,这些单词可以是任意内容,但通常会在其中指定一些与消息相关的特性。请看一些合法的路由键示例:stock.usd.nyse
,nyse.vmw
,quick.orange.rabbit
,路由键可以包含任意数量的单词,但不能超过255个字节的上限。
binding key
也必须是相同的形式,topic
交换器的背后逻辑与direct
交换器类似 - 使用指定路由键发送的消息会被分发到与其绑定键匹配的所有队列中。不过对于绑定键来说,有两个重要的特殊情况需要注意:
*
(星号)可以代替一个单词。#
(哈希)可以代替零个或多个单词。下图示例是对上述内容最简单的解释:
在这个示例中,我们打算发送的消息全是用来描述动物的,这些消息会使用由三个单词(两个点)组成的路由键来发送。在路由键中,第一个单词用来描述行动速度、第二个是颜色、第三个是物种,即:<speed>.<colour>.<species>
。
我们创建了三个绑定:Q1绑定了键.orange.
,Q2绑定了键*.*.rabbit
和lazy.#
。
这些绑定可以被概括为:
Q1对所有橙色的动物感兴趣。Q2对兔子以及所有行动缓慢的动物感兴趣。路由键为quick.orange.rabbit
的消息会被发送到这两个队列,消息lazy.orange.elephant
也会被发送到这两个队列。另外,quick.orange.fox
只会进入第一个队列,lazy.brown.fox
只会进入第二个队列。lazy.pink.rabbit
只会被发送到第二个队列一次,尽管它匹配了两个绑定(避免了消息重复)。quick.brown.fox
没有匹配的绑定,因此它将会被丢弃。
如果我们打破约定,发送使用一个或四个单词(例如:orange
和quick.orange.male.rabbit
)作路由键的消息会发生什么?答案是,这些消息因为没有匹配到任何绑定,将被丢弃。
但是,另外,例如路由键为lazy.orange.male.rabbit
的消息,尽管它有四个单词,也会匹配最后一个绑定,并将被发送到第二个队列。
Topics 交换器
topic
交换器的功能是很强大的,它可以表现出一些其他交换器的行为。
当一个队列与键#
(哈希)绑定时, 它会忽略路由键,接收所有消息,这就像fanout
交换器一样。
当特殊字符*
(星号)和#
(哈希)未在绑定中使用时,topic
交换器的行为就像direct
交换器一样。
组合在一起
我们将要在我们的日志系统中使用topic
交换器,首先假设日志的路由键有两个单词组成:<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 > 0) ? args[0] : "anonymous.info"; var message = (args.Length > 1) ? string.Join(" ", args.Skip(1).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 < 1) { Console.Error.WriteLine("Usage: {0} [binding_key...]", Environment.GetCommandLineArgs()[0]); Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); Environment.ExitCode = 1; 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, autoAck: true, consumer: consumer); Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); } }}
请运行以下示例:
要接收所有日志:
cd ReceiveLogsTopicdotnet run "#"
要接收来自设备kern
的所有日志:
cd ReceiveLogsTopicdotnet run "kern.*"
或者,如果您只想监听级别为critical
的日志:
cd ReceiveLogsTopicdotnet run "*.critical"
您可以创建多个绑定:
cd ReceiveLogsTopicdotnet run "kern.*" "*.critical"
使用路由键kern.critical
发出日志:
cd EmitLogTopicdotnet run "kern.critical" "A critical kernel error"
希望运行这些程序能让您玩得开心。要注意的是,这些代码没有针对路由键和绑定键做任何预设,您可以尝试使用两个以上的路由键参数。
( EmitLogTopic.cs 和 ReceiveLogsTopic.cs 的完整源码)
接下来,在 教程[6] 中将了解如何将往返消息作为远程过程调用。
写在最后
本文翻译自RabbitMQ官方教程C#版本。如本文介绍内容与官方有所出入,请以官方最新内容为准。水平有限,翻译的不好请见谅,如有翻译错误还请指正。
原文链接:RabbitMQ tutorial - Topics
实验环境:RabbitMQ 3.7.4 、.NET Core 2.1.3、Visual Studio Code
最后更新:2018-09-06
相关产品
-
虽然喷气机在常规赛拿到了15胜5平7负的不俗战绩,但是面对墨尔本城这个对手,喷气机本赛季的战绩并不占优。本赛季,双方曾三次交手,喷气机1平2负未尝胜绩,墨尔本城也成为了本赛季喷气机唯一未能战胜的对手,所以虽然是客场作战,但是墨尔本城在心理上还是占据了一定优势的。
-
接近凌晨4点,中国人民解放军总医院第一附属医院为朱女士做了血清检查,结果显示其淋巴细胞百分比超标,快速肌酐低于正常水平,诊断为过敏性皮炎,经过神经内科检查后,医生表示不能排除为蚊虫叮咬导致的面部神经炎。但医生表示,因朱女士处于哺乳期,所开的药服用时有所禁忌,朱女士应于一周后到医院再进行复查,后续治疗方案视其恢复结果而定。
-
报道评论称,最后作出这一访问决定的正是奥巴马本人。之前就已经对广岛访问有过探究,此次奥巴马终于下定决心,其背景中主要有两个想法或目的:一个是2009年奥巴马对在布拉格演讲中提出的“无核武器的世界”的坚持。东北亚在存在着严峻的朝鲜核武器开发问题的状况下,对“最开始变成核武器牺牲品的广岛”进行访问,再次表明奥巴马的信念,这对于他推迟尚未完成的核裁减与核不扩散具有很大的意义。
-
动力方面:新款奔驰威霆采用新型2.5的V6发动机,5速自动变速箱,低耗高效、马力强劲汹涌;配备电子稳定程序ESP,搭载SBS、ASR、BAS及EBV系统,主动安全性与顶级轿车媲美。
-
此次事件,让在模特圈小有名气的野崎萌香形象大受挫,然而让网友更气愤的是,事情过去了几天,这两位麻豆以及各自所属事务所都没有对此事作出回应…▼
-
报道指出,装配一台快速充电设备的费用大概在500万日元(约合人民币30.6万元),其中每台充电器从日本政府处最多可以获得2/3的补贴,剩下的装配费用则由该4家车企共同承担。
-
第一批“00后”陆续成年,他们已开始加入庞大的职工队伍中。相较城市里的“00后”,他们开始从懵懂少年变成了“新社会人”。有的想通过打工学习技能,为了找到更好机会;有的早早为家庭分担。他们已不再是“小朋友”了!
-
暑期来临,为了让孩子们远离手机、电脑和电视,台北市政府规划了一系列青少年休闲娱乐活动,内容包括知性艺文类、休闲活动类及技能研习类、体育竞赛类等6大类近700项活动,希望孩子们“运动一夏”、“欢乐一夏”。
热点资讯
- 信邦制药股东马晟合计减持500万股套现约2250万元2019-06-26
- 中共中央办公厅印发《关于统筹规范督查检查考核工作的通知》2019-06-26
- 旅游必备岳圣旅游管家卡:专业当地导游带你畅游古韵长安,一站吃遍陕西美食!2019-06-26
- 刘强东案律师代理律师:民事诉讼将被提起,我们不允许隐瞒真相。2019-06-26
- 探寻“袖剑之父”背后的故事《刺客信条:奥德赛》首部资料片公开2019-06-26
- 调查:2018年英国人平均每天花3小时8分钟上网2019-06-26
- 也门和谈一致认为,霍迪达停火时间没有透露。2019-06-26
- 鸭掌木的养殖维护方法和注意事项2019-06-26