zoukankan      html  css  js  c++  java
  • RabbitMQ

    RabbitMQ教程C#版 - “Hello World”

     

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

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

    1.介绍

    RabbitMQ是一个消息代理:它接受并转发消息。您可以把它想象成一个邮局:当您将需要寄出的邮件投递到邮箱,您可以确定的是邮差先生最终会将邮件送给您的收件人。在这个比喻中,RabbitMQ就是一个邮箱,也可以理解成邮局和邮递员。

    RabbitMQ和邮局的主要区别在于它不处理纸张,而是接收、存储和转发二进制数据块 - 消息

    RabbitMQ和消息传递通常使用一些术语。

    生产的意思无非就是发送。发送消息的程序就是一个生产者

    Producer

    队列就是RabbitMQ内部“邮箱”的名称。虽然消息流经RabbitMQ和您的应用程序,但它们只能存储在队列中。队列只受主机的内存和磁盘的限制,它本质上就是一个很大的消息缓冲区。多个生产者可以发送消息到一个队列,并且多个消费者可以尝试从一个队列接收数据。这就是我们代表队列的方式:

    Queue

    消费与接收有相似的含义。主要等待接收消息的程序就是一个消费者

    Consumer

    注意:生产者、消费者和中间件不是必须部署在同一主机上,实际上在大多数应用程序中它们不是。

    2."Hello World"

    2.1.使用.NET / C#客户端

    在教程的这一部分,我们将用C#编写两个程序:一个发送单条消息的生产者,以及接收消息并将其打印出来的消费者。我们将忽略.NET客户端API中的一些细节,专注于更简单的开始。这是一个消息传递的“Hello World”。

    在下图中,“P”是我们的生产者,“C”是我们的消费者。中间的盒子是队列 - RabbitMQ代表消费者保存的消息缓冲区。

    image

    .NET客户端库
    RabbitMQ支持多种协议,本教程使用AMQP 0-9-1,它是一种开放的、通用的消息传递协议。RabbitMQ提供了一些针对不同语言环境的客户端,我们将使用RabbitMQ提供的.NET客户端。

    客户端支持.NET Core以及.NET Framework 4.5.1+。本教程将使用.NET Core,因此您需要确保客户端已安装并且路径添加到PATH系统变量。

    您也可以使用.NET Framework来完成本教程,但设置步骤会有所不同。

    RabbitMQ .NET客户端5.0及更高版本通过nuget发布。

    本教程假定您在Windows上使用PowerShell。在MacOS和Linux上,几乎所有shell也都可以正常工作。

    2.2.安装

    首先让我们验证您在PATH系统变量是否有.NET Core工具链:

    dotnet --help

    应该产生帮助信息。

    现在,让我们生成两个项目,一个用于发布者,另一个用于消费者:

    dotnet new console --name Send
    mv Send/Program.cs Send/Send.cs
    dotnet new console --name Receive
    mv Receive/Program.cs Receive/Receive.cs

    这将创建两个名为SendReceive的新目录。

    然后,我们添加客户端依赖项。

    cd Send
    dotnet add package RabbitMQ.Client
    dotnet restore
    cd ../Receive
    dotnet add package RabbitMQ.Client
    dotnet restore

    我们已经建立了.NET项目,现在我们可以编写一些代码。

    2.3.发送

    Sending

    我们将调用我们的消息发布者(发送者)Send.cs和我们的消息消费者(接收者)Receive.cs。发布者将连接到RabbitMQ,发送一条消息,然后退出。

    Send.cs中,我们需要使用一些命名空间:

    using System;
    using RabbitMQ.Client;
    using System.Text;

    设置类:

    class Send
    {
        public static void Main()
        {
            ...
        }
    }

    然后,我们可以创建一个连接,连接到服务器:

    class Send
    {
        public static void Main()
        {
            var factory = new ConnectionFactory() { HostName = "localhost" };
            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    ...
                }
            }
        }
    }

    该连接抽象了套接字连接,并为我们处理协议版本的协商和身份验证等。在这里,我们连接的是本地机器上的代理, 因此是localhost。如果我们想连接到其他机器上的代理,我们只需在此指定其名称或IP地址。

    接下来,我们创建一个通道,该API的主要功能是把获得信息保存起来。

    要发送,我们必须为我们需要发送的消息声明一个队列,然后我们可以把消息发布到队列中:

    using System;
    using RabbitMQ.Client;
    using System.Text;
    
    class Send
    {
        public static void Main()
        {
            var factory = new ConnectionFactory() { HostName = "localhost" };
            using(var connection = factory.CreateConnection())
            using(var channel = connection.CreateModel())
            {
                channel.QueueDeclare(queue: "hello",
                                     durable: false,
                                     exclusive: false,
                                     autoDelete: false,
                                     arguments: null);
    
                string message = "Hello World!";
                var body = Encoding.UTF8.GetBytes(message);
    
                channel.BasicPublish(exchange: "",
                                     routingKey: "hello",
                                     basicProperties: null,
                                     body: body);
                Console.WriteLine(" [x] Sent {0}", message);
            }
    
            Console.WriteLine(" Press [enter] to exit.");
            Console.ReadLine();
        }
    }

    声明队列是幂等的 - 只有当它不存在时才会被创建。消息内容是一个字节数组,所以您可以用喜欢的任意方式编码。

    当上面的代码完成运行时,通道和连接将被释放。这就是我们的发布者。

    发送不起作用!
    如果这是您第一次使用RabbitMQ,并且您没有看到“已发送”消息,那么您可能会挠着头想知道错误出在什么地方。也许是代理程序启动时没有足够的可用磁盘空间(默认情况下,它至少需要50 MB空闲空间),因此拒绝接收消息。
    必要时检查代理程序日志文件来确认和减少限制。配置文件文档将告诉您如何设置disk_free_limit

    2.4.接收

    至于消费者,它是把消息从RabbitMQ拉取过来。因此,与发布消息的发布者不同,我们会保持消费者持续不断地运行,监听消息并将其打印出来。

    Receiving

    代码(在Receive.cs中)具有与Send差不多一样的using声明:

    using RabbitMQ.Client;
    using RabbitMQ.Client.Events;
    using System;
    using System.Text;

    设置与发布者相同;我们开启一个连接和一个通道,并声明我们将要使用的队列。请注意,这需要与Send发布到的队列相匹配。

    class Receive
    {
        public static void Main()
        {
            var factory = new ConnectionFactory() { HostName = "localhost" };
            using (var connection = factory.CreateConnection())
            {
                using (var channel = connection.CreateModel())
                {
                    channel.QueueDeclare(queue: "hello",
                                         durable: false,
                                         exclusive: false,
                                         autoDelete: false,
                                         arguments: null);
                    ...
                }
            }
        }
    }

    请注意,我们在这里也声明了队列。因为我们可能会在发布者之前启动消费者,所以我们希望在我们尝试从它中消费消息之前确保队列已存在。

    我们即将告诉服务器将队列中的消息传递给我们。由于它会异步推送消息,因此我们提供了一个回调。这就是EventingBasicConsumer.Received事件处理程序所做的事情。

    using RabbitMQ.Client;
    using RabbitMQ.Client.Events;
    using System;
    using System.Text;
    
    class Receive
    {
        public static void Main()
        {
            var factory = new ConnectionFactory() { HostName = "localhost" };
            using(var connection = factory.CreateConnection())
            using(var channel = connection.CreateModel())
            {
                channel.QueueDeclare(queue: "hello",
                                     durable: false,
                                     exclusive: false,
                                     autoDelete: false,
                                     arguments: null);
    
                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body;
                    var message = Encoding.UTF8.GetString(body);
                    Console.WriteLine(" [x] Received {0}", message);
                };
                channel.BasicConsume(queue: "hello",
                                     autoAck: true,
                                     consumer: consumer);
    
                Console.WriteLine(" Press [enter] to exit.");
                Console.ReadLine();
            }
        }
    }

    2.5.组合在一起

    打开两个终端。

    运行消费者:

    cd Receive
    dotnet run

    运行生产者:

    cd Send
    dotnet run

    消费者将打印它通过RabbitMQ从发布者处获得的消息。消费者将继续运行、等待新消息(按Ctrl-C将其停止),可以尝试从开启另一个终端运行发布者。

    3.写在最后

    本文翻译自RabbitMQ官方教程。水平有限,翻译的不好请见谅,如有翻译错误还请指正。

  • 相关阅读:
    构建一个应用,并在docker compose里运行起来
    docker engine docker-compose部署
    django 返回数据的几种常用姿势
    fiddler+httprunner 零编码实现接口自动化DEMO
    选择排序
    曾经学的那些表示时间复杂度的公式怎么来的?
    python+Airtest+android使用AirtestIDE编写一个DEMO
    怎么计算时间复杂度?
    算法_冒泡排序python+java实现
    2020年1月16日(多进程)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/8578741.html
Copyright © 2011-2022 走看看