(四)「消息队列」之 RabbitMQ 路由(使用 .NET 客户端)

0、引言

先决条件

本教程假设 RabbitMQ 已安装并且正在 本地主机 的标准端口(5672)上运行。如果您使用了不同的主机、端口或凭证,则要求调整连接设置。

获取帮助

如果您在阅读本教程时遇到问题,可以通过邮件列表或者 RabbitMQ 社区 Slack 与 RabbitMQ 官方取得联系。

在上一篇教程中我们构建了一个简单的日志系统,得以向许多接收者(receiver)广播日志消息。

在本教程中我们将会为该系统添加一个特性 —— 我们将使“仅订阅消息的一个子集”成为可能。例如,我们将能够只将关键错误消息定向到日志文件(以节省磁盘空间),与此同时仍然能够在控制台上打印所有的日志消息。

原文链接:https://www.rabbitmq.com/tutorials/tutorial-four-dotnet.html

1、绑定

在上一篇例程中我们已经建立过绑定了。您也许能够回想起,代码类似于:

channel.QueueBind(queue: queueName,exchange: "logs",routingKey: string.Empty);

绑定 即表征 交换机队列 之间的关系。这可以简单地理解为:队列对来自此交换机的消息感兴趣。

绑定可以接收一个额外的 routingKey (路由键)参数。为了避免与 BasicPublish 方法的一个参数混淆,我们现在将其称之为 binding key (绑定键)。下面演示了我们如何创建一个带有键的绑定:

channel.QueueBind(queue: queueName,exchange:"direct_logs",routingKey: "black");

binding key 的含义取决于交换机的类型。比如我们之前使用的 fanout 交换机会简单地忽略它的值。

2、直连交换机(Direct exchange)

在上一篇教程中,我们的日志系统向所有的消费者广播所有消息。我们希望对其进行拓展,以允许根据消息的严重程度过滤消息。比如,我们也许想要向磁盘写入日志消息的脚本文件只接收关键错误,而不是在警告或者信息日志消息上浪费磁盘空间。

但我们在上一篇教程使用的 fanout 扇出交换机并没有给我们如此大的灵活性 —— 它只能够进行无意识的广播。

相反,我们将会使用一个 direct 直连交换机。其背后的路由算法很简单 —— 将消息路由到其 routing key 与队列的 binding key 完全匹配的队列。

为了说明这一点,请考虑如下配置:

direct-exchange

在这个配置中,我们可以看到绑定了两个队列的 direct 直连交换机 X。第一个队列使用 orange 绑定键绑定;而第二个队列拥有两个绑定,一个绑定键为 black,另一个绑定键为 green

在这样的配置下,被发布到交换机中带有 orange 路由键的消息将会被路由到 Q1 队列。而带有 black 或者 green 路由键的消息将会去往 Q2 队列。其他所有消息将会被丢弃。

3、多个绑定

direct-exchange-multiple

使用相同的绑定键绑定多个队列是完全合法的。在我们的示例中,我们可以使用 black 绑定键在 XQ1 之间添加绑定。在那样的情况下,direct 直连交换机表现得像是 fanout 扇出交换机:向所有匹配的队列广播消息。带有 black 路由键的消息将同时传递给 Q1Q2 双方。

4、发送日志

我们将在日志系统中使用这个模型,我们将消息发送至 direct 直连交换机而不是 fanout 扇出交换机。我们提供日志严重程序作为 routing key 路由键。这样接收脚本就能够选择其想要接收的严重程度。让我们首先关注发送日志:

如常,首先我们需要创建一个交换机:

channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct);

我们已经准备好发送一条消息:

var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "direct_logs",routingKey: severity,basicProperties: null,body: body);

为了简化问题我们假定 ‘严重程度’ 可以是 infowarningerror 中的一个。

5、订阅

接收消息的方式工作与上一篇教程类似,但有一点例外 —— 我们将会为我们感兴趣的每个 ‘严重程度’ 创建新的绑定。

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

6、将所有的东西放到一起

tutorial-four

EmitLogDirect.cs 类的代码:

using System.Text;
using RabbitMQ.Client;var factory = new ConnectionFactory { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.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 '{severity}':'{message}'");Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();

ReceiveLogsDirect.cs 的代码:

using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;var factory = new ConnectionFactory { HostName = "localhost" };using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();channel.ExchangeDeclare(exchange: "direct_logs", type: ExchangeType.Direct);
// declare a server-named queue
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.ToArray();var message = Encoding.UTF8.GetString(body);var routingKey = ea.RoutingKey;Console.WriteLine($" [x] Received '{routingKey}':'{message}'");
};
channel.BasicConsume(queue: queueName,autoAck: true,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();

像往常一样创建项目(建议参考教程一)

如果您只想要保存 warningerror(没有 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.'

(EmitLogDirect.cs 和 ReceiveLogsDirect.cs 的完整源码)

运行效果:
在这里插入图片描述

要了解如何基于特定模式侦听消息,请移步至教程五。

5、生产[非]适用性免责声明

请记住,本教程和其他教程都是教程。他们一次展示一个新概念,可能会有意地过度简化一些东西,而忽略其他东西。例如,为了简洁起见,连接管理、错误处理、连接恢复、并发性和指标收集等主题在很大程度上被省略了。这种简化的代码不应该被认为可以用于生产。

在发布您的应用之前,请先查看其他文档。我们特别推荐以下指南:发布者确认和消费者确认,生产清单和监控。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3708.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Meta发布升级大模型LLaMA 2:开源可商用

论文地址&#xff1a;https://ai.meta.com/research/publications/llama-2-open-foundation-and-fine-tuned-chat-models/ Github地址&#xff1a;https://github.com/facebookresearch/llama LLaMA 2介绍 Meta之前发布自了半开源的大模型LLaMA&#xff0c;自从LLaMA发布以来…

C# WPF实现动画渐入暗黑明亮主题切换效果

C# WPF实现动画渐入暗黑明亮主题切换效果 效果图如下最近在Bilibili的桌面端看到一个黑白主题切换的效果感觉&#xff0c;挺有意思。于是我使用WPF尝试实现该效果。 主要的切换效果&#xff0c;基本实现不过还存在一些小瑕疵&#xff0c;比如字体等笔刷不能跟随动画进入进行切…

Docker简介

Docker简介 文章目录 Docker简介一、Docker1.什么是docker?2.容器引擎3.容器和虚拟机的区别4.namespace&#xff08;命名空间&#xff09;5.三大容器核心概念镜像容器仓库 二、Docker镜像操作1.搜索镜像2.获取镜像镜像加速下载 3.查看本地下载镜像4.获取镜像详细信息5.为本地镜…

SQL 上升的温度

197 上升的温度 SQL架构 表&#xff1a; Weather ---------------------- | Column Name | Type | ---------------------- | id | int | | recordDate | date | | temperature | int | ---------------------- id 是这个表的主键 该表包含特定日期的温度信息 编写一个 SQL …

事务@transactional执行产生重复数据

背景 系统设计之初&#xff0c;每次来新请求&#xff0c;业务层会先查询数据库&#xff0c;判断是否存在相同的id数据&#xff08;id是唯一标识产品的&#xff09;&#xff0c;有则返回当前数据库查到的数据&#xff0c;根据数据决定下一步动作&#xff0c;没有则认为是初次请…

销售自动化如何提高团队生产力?从这5个方面发力

任何用于减少人工劳动和缩短销售流程相关任务时间的技术&#xff0c;都可定义为销售自动化。 对于忙碌的销售人员来说&#xff0c;流程自动化是真正的救星。它可以使他们的工作简化30%&#xff0c;让他们更专注于创收任务。这将显著提高团队的工作效率&#xff0c;并带来许多其…

滑动奇异频谱分析:数据驱动的非平稳信号分解工具(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

师承AI世界新星|7天获新加坡南洋理工大学访学邀请函

能够拜师在“人工智能10大新星”名下&#xff0c;必定可以学习到前沿技术&#xff0c;受益良多&#xff0c;本案例中的C老师无疑就是这个幸运儿。我们只用了7天时间就取得了这位AI新星导师的邀请函&#xff0c;最终C老师顺利获批CSC&#xff0c;如愿出国。 C老师背景&#xff1…

Leetcode刷题4

⼆叉树、BFS、堆、Top K、⼆叉搜索树、模拟、图算法 一、二叉树 二叉树的前序中序后序 二叉树节点定义 为了方便演示&#xff0c;我们先定义一个二叉树节点类。 class TreeNode:def __init__(self, val0, leftNone, rightNone):self.val valself.left leftself.right r…

Android ViewGroup onDraw为什么没调用

ViewGroup&#xff0c;它本身并没有任何可画的东西&#xff0c;它是一个透明的控件&#xff0c;因些并不会触发onDraw&#xff0c;但是你现在给LinearLayout设置一个背景色&#xff0c;其实这个背景色不管你设置成什么颜色&#xff0c;系统会认为&#xff0c;这个LinearLayout上…

[回馈]ASP.NET Core MVC开发实战之商城系统(开篇)

在编程方面&#xff0c;从来都是实践出真知&#xff0c;书读百遍其义自见&#xff0c;所以实战是最好的提升自己编程能力的方式。 前一段时间&#xff0c;写了一些实战系列文章&#xff0c;如&#xff1a; ASP.NET MVC开发学生信息管理系统VueAntdvAsp.net WebApi开发学生信息…

R语言的水文、水环境模型优化技术及快速率定方法与多模型案例实践

在水利、环境、生态、机械以及航天等领域中&#xff0c;数学模型已经成为一种常用的技术手段。同时&#xff0c;为了提高模型的性能&#xff0c;减小模型误用带来的风险&#xff1b;模型的优化技术也被广泛用于模型的使用过程。模型参数的快速优化技术不但涉及到优化本身而且涉…

Python中的break和continue语句应用举例

Python中的break和continue语句应用举例 在进行Python编程时候&#xff0c;有时需要&#xff0c;对循环中断或跳过某部分语句&#xff0c;此时常会用到break语句或continue语句。本文将通过实际例子阐述这两个语句的用法。 1.break语句 break语句是实现在某个地方中断循环&a…

Java设计模式之行为型-迭代器模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色设计 四、案例分析 五、总结 一、基础概念 迭代器模式是一种常用的设计模式&#xff0c;它主要用于遍历集合对象&#xff0c;提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不暴露该对象的内部表示。 举个简单的…

5分钟给你破解这套10万赞的生产教程,访谈乔布斯的AI对话数字人视频是怎么做的

本期是赤辰第16期AI项目拆解栏目&#xff1b; 底部准备了7月粉丝福利&#xff0c;看完可以领取&#xff1b; 上周给粉丝们讲解AI动图说话月涨粉20万的案例并给出保姆式教程&#xff0c;粉丝反馈很热烈&#xff0c;都觉得AI强大&#xff0c;有些学员给自己账号做视频&#xff…

大数据与视频技术的融合趋势将带来怎样的场景应用?

视频技术和AI技术的融合是一种新兴的技术趋势&#xff0c;它将改变视频行业的运作方式。视频技术和AI技术的融合主要包括以下几个方面&#xff1a; 1&#xff09;人脸识别技术 人脸识别技术是AI技术的一个重要应用场景。它可以通过对视频中的人脸进行识别和分析&#xff0c;实…

3.9 Bootstrap 分页

文章目录 Bootstrap 分页分页&#xff08;Pagination&#xff09;默认的分页分页的状态分页的大小 翻页&#xff08;Pager&#xff09;默认的翻页对齐的链接翻页的状态 分页 Bootstrap 分页 本章将讲解 Bootstrap 支持的分页特性。分页&#xff08;Pagination&#xff09;&…

Unity平台如何实现RTSP转RTMP推送?

技术背景 Unity平台下&#xff0c;RTSP、RTMP播放和RTMP推送&#xff0c;甚至包括轻量级RTSP服务这块都不再赘述&#xff0c;今天探讨的一位开发者提到的问题&#xff0c;如果在Unity下&#xff0c;实现RTSP播放的同时&#xff0c;随时转RTMP推送出去&#xff1f; RTSP转RTMP…

浙大数据结构第四周之04-树6 Complete Binary Search Tree

题目详情&#xff1a; A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node contains only nodes with keys less than the nodes key.The right subtree of a node contains only nodes w…

[javascript核心-08] V8 内存管理机制及性能优化

V8 内存管理 V8 本身也是程序&#xff0c;它本身也会申请内存&#xff0c;它申请的内存称为常驻内存&#xff0c;而它又将内存分为堆和栈 栈内存 栈内存介绍 栈用于存放JS 中的基本类型和引用类型指针栈空间是连续的&#xff0c;增加删除只需要移动指针&#xff0c;操作速度…