[译]RabbitMQ教程C#版 - 发布订阅

先决条件
本教程假定RabbitMQ已经安装,并运行在localhost标准端口(5672)。如果你使用不同的主机、端口或证书,则需要调整连接设置。

从哪里获得帮助
如果您在阅读本教程时遇到困难,可以通过邮件列表联系我们。

1.发布/订阅

(使用.NET客户端)

在教程[2]中,我们创建了一个工作队列,假设在工作队列中的每一个任务都只被分发给一个Worker。那么在这一章节,我们要做与之完全不同的事,那就是我们将要把一条消息分发给多个消费者。这种模式被称为“发布/订阅”。

为了说明、体现这种模式,我们将会建一个简单的日志系统。它将会包含两个程序 - 第一个用来发送日志消息,第二个用来接收并打印它们。

在我们建立的日志系统中,每个接收程序的运行副本都会收到消息。这样我们就可以运行一个接收程序接收消息并将日志写入磁盘;同时运行另外一个接收程序接收消息并将日志打印到屏幕上。

实质上,发布的日志消息将会被广播给所有的接收者。

2.交换器

在教程的前几部分,我们是发送消息到队列并从队列中接收消息。现在是时候介绍Rabbit中完整的消息传递模型了。

让我们快速回顾一下前面教程中的内容:

  • 生产者是发送消息的用户应用程序。

  • 队列是存储消息的缓冲区。

  • 消费者是接收消息的用户应用程序。

在RabbitMQ中,消息传递模型的核心理念是生产者从来不会把任何消息直接发送到队列,其实,通常生产者甚至不知道消息是否会被分发到任何队列中。

然而,生产者只能把消息发送给交换器。交换器非常简单,一方面它接收来自生产者的消息,另一方面又会把接收的消息推送到队列中。交换器必须明确知道该如何处理收到的消息,应该追加到一个特定队列中?还是应该追加到多个队列中?或者应该把它丢弃?这些规则都被定义在交换器类型中。

640?wx_fmt=png

目前有这几种的交换器类型可用:direct,topic,headers和fanout。我们重点关注最后一个 -- fanout,让我们来创建一个这种类型的交换器,将其命名为logs:

channel.ExchangeDeclare("logs", "fanout");

fanout类型交换器非常简单。正如您可能从名字中猜出的那样,它会把收到的所有消息广播到它已知的所有队列中。这恰巧是我们的日志系统所需要的。

列举交换器
要列举出服务器上的交换器,您可以使用非常有用的rabbitmqctl命令行工具:

sudo rabbitmqctl list_exchanges

执行上述命令后,出现的列表中将会有一些amq.*交换器和默认(未命名)交换器。这些是默认创建的,不过目前您可能用不到它们。

默认交换器
在教程的前些部分,我们对交换器这一概念还一无所知,但仍然可以把消息发送到队列。之所以这样,是因为我们使用了一个用空字符串("")标识的默认交换器。

回顾一下我们之前如何发布消息:

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

第一个参数就是交换器的名称,空字符串表示默认或匿名交换器:将消息路由到routingKey指定的队列(如果存在)中。

现在,我们可以把消息发布到我们指定的交换器:

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

3.临时队列

您是否还记得之前我们使用过的队列,它们都有一个特定的名称(记得应该是hello和task_queue吧)。给队列命名对我们来说是至关重要的 -- 因为我们可能需要多个Worker指向同一个队列;当您想要在生产者和消费者之间共享队列时,给队列一个名称也是非常重要的。

但是,我们创建的日志系统并不希望如此。我们希望监听所有的日志消息,而不仅仅是其中一部分。我们也只对目前流动的消息感兴趣,而不是旧消息。为解决这个问题,我们需要做好两件事。

首先,我们无论何时连接Rabbit,都需要一个新的、空的队列。要做到这一点,我们可以使用随机名称来创建队列,或许,甚至更好的方案是让服务器为我们选择一个随机队列名称。

其次,一旦我们与消费者断开连接,与之相关的队列应该被自动删除。

在.NET客户端中,如果不向QueueDeclare()方法提供任何参数,实际上就是创建了一个非持久化、独占、且自动删除的随机命名队列:

var queueName = channel.QueueDeclare().QueueName;

您可以在队列指南中了解更多关于exclusive参数和其他队列属性的信息。

此时,queueName包含一个随机队列名称。例如,它看起来可能像amq.gen-JzTY20BRgKO-HjmUJj0wLg。

4.绑定

640?wx_fmt=png

我们已经创建好了一个fanout交换器和一个队列。现在我们需要告诉交换器把消息发送到我们的队列。而交换器和队列之间的关系就称之为绑定。

// 把一个队列绑定到指定交换器。channel.QueueBind(queue: queueName,                  exchange: "logs",                  routingKey: "");

从现在起,logs交换器会把消息追加到我们的队列中。

列举绑定
您可以使用(您或许已经猜到了),列举出现有的绑定。

sudo rabbitmqctl list_bindings

5.组合在一起

640?wx_fmt=png

生产者程序负责分发消息,这与之前的教程看起来没有太大区别。

最重要的变化是我们现在想把消息发布到我们的logs交换器,而不是匿名交换器。在发送时我们需要提供一个路由键routingKey,但是对于fanout交换器,它的值可以被忽略。这里是EmitLog.cs文件的代码:

640?wx_fmt=png

(EmitLog.cs源码)

如你所见,在建立连接后,我们声明了交换器。这一步非常有必要,因为发布消息到一个不存在的交换器,这种情况是被禁止的。

如果没有队列绑定到交换器上,消息将会丢失,但这对我们来说并没有什么没问题;如果没有消费者正在监听,我们是可以放心地把消息丢弃的。

ReceiveLogs.cs的代码:

640?wx_fmt=png

(ReceiveLogs.cs源码)

按照教程[1]中的设置说明生成EmitLogs和ReceiveLogs项目。

如果您想把日志保存到文件中,只需打开一个控制台并输入:

cd ReceiveLogs
dotnet run > logs_from_rabbit.log

如果你想在屏幕上看到日志,我可以新开一个终端并运行:

cd ReceiveLogs
dotnet run

当然,分发日志需要输入:

cd EmitLog
dotnet run

使用rabbitmqctl list_bindings命令,您可以验证代码是否真正创建了我们想要的绑定和队列。当有两个ReceiveLogs.cs程序运行时,您应该看到如下所示的内容:

sudo rabbitmqctl list_bindings# => Listing bindings ...# => logs    exchange        amq.gen-JzTY20BRgKO-HjmUJj0wLg  queue           []# => logs    exchange        amq.gen-vso0PVvyiRIL2WoV3i48Yg  queue           []# => ...done.

对执行结果的解释简洁明了:来自logs交换器的数据转发到了两个由服务器随机分配名称的队列。这正是我们期待的结果。

想要了解如何监听消息的这一块内容,让我们继续阅读教程[4]。

6.写在最后

本文翻译自RabbitMQ官方教程C#版本。本文介绍如与官方有所出入,请以官方最新内容为准。

水平有限,翻译的不好请见谅,如有翻译错误还请指正。

  • 原文链接:RabbitMQ tutorial - Publish/Subscribe

  • 实验环境:RabbitMQ 3.7.4 、.NET Core 2.1.3、Visual Studio Code

  • 最后更新:2018-06-11

作者:Esofar

出处:http://www.cnblogs.com/esofar/p/rabbitmq-publish-subscribe.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

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

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

相关文章

用ASP.NET Core 2.1 建立规范的 REST API -- 缓存和并发

本文所需的一些预备知识可以看这里: 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 和 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) 准备项目建立Richardson成熟度2级的POST、GET、PUT、PATCH、DELETE的RESTful API请看这里:用ASP.NET Core …

2017 SEERC Divide and Conquer 树上差分

题目 题目大意:给出两颗树的复合图(即这张图是由两颗树拼起来的),询问最小割掉多少条边,可以使得图不联通,并输出方案数。 分析 我觉得这是一道很难的题目,因为比较难想,前提结论比较多。 首先我们需要…

青蛙跳荷叶

青蛙跳荷叶 题目大意: 有n个点,从1开始到跳完这些点,且每次的距离不能相等,一个点不能到多次 原题: 题目描述 从前,有一个小青蛙决定去荷叶上练习跳跃.现在有n个荷叶排成一排,小青蛙一开始…

基于 Consul 实现 MagicOnion(GRpc) 服务注册与发现

0.简介0.1 什么是 ConsulConsul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。这里所谓的服务,不仅仅包括常用的 Api 这些服务,也包括软件开发过程当中所需要的诸如 Rpc、Redis、Mysql 等需要调用的资源。简而言之 Con…

【DFS】排排坐

排排坐 题目大意: 有n个方块,有一些是黑色,有一些是白色,可以点击一个方块使它和它旁边的方块反转颜色(黑变白,白变黑),问最少要点多少次才能将方块 们 变成目标的方块们&#xff…

用ASP.NET Core 2.1 建立规范的 REST API -- 保护API和其它

预备知识: 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 用ASP.NET Core 2.0 建立规范的 REST API -- 预备知识 (2) 准备项目建立成熟度2级的 API请看这里:用ASP.NET Core 2.0 建立规范的 REST API -- GET 和 POST, 用ASP.NET Core 2.0 建立规范的 REST AP…

华为资深工程师:码农很多,但程序员并不多......

“春节假期,与几位友人小聚,大家互道工作顺利、平安健康云云......期间一位驰骋商界多年的老友问:“你现在在华为做什么工作呀?”我很骄傲地说:”系统架构师“,可是他却愣了很久。但当我老婆在旁边补上一句“码农“时…

VS2017 15.8第二个预览版本提升了对CPU Profiling和F#的支持

VS2017 15.8第一个预览版本的特性包括对ARM64构建的支持、ASP.NET Core对Docker的支持以及重新引入LibMan。在15.8的第二个预览版本中,微软发布了一个新Google Android模拟器的预览功能,它能够与Hyper-V兼容。这样的话,最新的Android模拟器就…

ASP.NET Core Razor生成Html静态文件

一、前言最近做项目的时候,使用Util进行开发,使用Razor写前端页面。初次使用感觉还是不大习惯,之前都是前后端分离的方式开发的,但是使用Util封装后的Angular后,感觉开发效率还是杠杠滴。二、问题在发布代码的时候&…

一文看懂.NET的各种变体

曾几何时,我们只有一个.NET,叫作.NET Framework。如果想要开发.NET应用程序,只要使用.NET Framework即可,非常简单。几年之后,出现了.NET变种的寒武纪大爆发(我们称之为“.NET大爆炸”)&#xf…

【最短路】【Floyed】医院设置(ssl 1614)

医院设置 ssl 1614 题目大意: 有n个点,在一个点上安医院,使这个点到其他点的最短路之和最小 原题: Description 设有一棵二叉树(如右图)。其中,圈中的数字表示结点中居民的人口。圈边上数…

拓展 NLog 优雅的输送日志到 Logstash

在上上篇博客通过对aspnetcore启动前配置做了一些更改,以及对nlog进行了自定义字段,可以把请求记录输送到mysql,正式情况可能不会这么部署。因为近期也在学习elk,所以就打算做一个实例,结合nlog把日志输送到logstash&a…

曼哈顿距离与切比雪夫距离的转化及prufer序列

目录 曼哈顿距离与切比雪夫距离的相互转化prufer序列 1. 曼哈顿距离 与 切比雪夫距离 的相互转化 曼哈顿距离 |x1−x2||y1−y2|max(x1−x2y1−y2,x1−x2−y1y2,−x1x2y1−y2,−x1x2−y1y2)|x1−x2||y1−y2|max(x1−x2y1−y2,x1−x2−y1y2,−x1x2y1−y2,−x1x2−y1y2)|x_1 - x…

[译]如何在.NET Core中使用System.Drawing?

你大概知道System.Drawing,它是一个执行图形相关任务的流行的API,同时它也不属于.NET Core的一部分。最初是把.NET Core作为云端框架设计的,它不包含非云端相关API。另一方面,.NET Core是跨平台框架,它不包含任何操作系…

关于Visual Studio 2019的前期详情

近日,来自微软公司的 John Montgomery 正式宣布,Visual Studio 2019已进入开发阶段。Montgomery 表示,之所以选择在这个时间点公开这个消息,是因为微软准备在 GitHub 上公开可见的项目(包括 .NET 和 Roslyn&#xff09…

开源的,跨平台的.NET机器学习框架ML.NET

微软在Build 2018大会上推出的一款面向.NET开发人员的开源,跨平台机器学习框架ML.NET。 ML.NET将允许.NET开发人员开发他们自己的模型,并将自定义ML集成到他们的应用程序中,而无需事先掌握开发或调整机器学习模型的专业知识。在采用通用机器学…

虚树-树上动态规划的利器

虚树 问题引入 在一类树上动态规划问题中,题目给出的询问往往包含树上的很多各节点,并保证总的点数规模小于某个值. 如果我们直接在整颗树上进行dpdp的话,时间复杂度与询问的次数有关,这显然是不可接受的,如果我们可以找到一种动态规划的方法,使其时间复杂度与询问中点的实际…

微软推出Visual Studio Kubernetes工具包预览版

微软表示,利用 Visual Studio Kubernetes 这个工具,使用者可以直接在该环境中,构建 Kubernetes 容器应用程序项目,或者让现有的 .NET 网页应用程序也兼容 Kubernetes。除了公有云基础架构环境要支持 Kubernetes,微软现…

基于docker 如何部署surging分布式微服务引擎

1、前言转眼间surging 开源已经有1年了,经过1年的打磨,surging已从最初在window 部署的分布式微服务框架,到现在的可以在docker部署利用rancher 进行服务编排的分布式微服务引擎,再把业务进行剥离, 通过配置路径就能驱…

DevOps 实践:千里之行

在上一篇 DevOps 渊源:角色消融 中我们分析了在作坊式团队中的责任重叠,也回顾了 DBA 角色的消融。那么,如今我们讲的 DevOps 又是什么角色的消融呢? 我想你已经猜到了,接下来要消融的角色就是运维人员了。那这次又是什…