zoukankan      html  css  js  c++  java
  • RabbitMQ系列教程之一:我们从最简单的事情开始!Hello World

    一、简介

          RabbitMQ是一个消息的代理器,用于接收和发送消息,你可以这样想,他就是一个邮局,当您把需要寄送的邮件投递到邮筒之时,你可以确定的是邮递员先生肯定会把邮件发送到需要接收邮件的人的手里,不会送错的。在这个比喻中,RabbitMQ就是一个邮箱,也可以理解为邮局和邮递员,他们负责把消息发送出去和用于接收信息。

       RabbitMQ和邮局这两者之间的主要区别是它不会处理纸质邮件,取而代之的是接收、存储和发送二进制数据块,也就是我们通常所说的消息。

       RabbitMQ和消息中,通常会使用一些专业术语。

       生产:生产意味着就是发送。 发送消息的程序是一个生产者。下图代表一个消息的生产真:

        

       队列:这里的队列是指一个名称,但是名称所代表的队列实体寄存在RabbitMQ服务器端中。 虽然消息流过RabbitMQ和您的应用程序,但它们只能存储在队列中。 队列只受主机的内存和磁盘的限制,它本质上是一个大的消息缓冲区。 许多生产者可以发送消息到一个队列,许多消费者可以尝试从一个队列接收数据。 下图代表一个队列:

       

       消费:消费具有与接收相似的含义。 消费者是一个主要等待接收消息的程序。下图代表消息的消费者:

        

    二、(使用 Net/C# 客户端)

       在这篇教程中我们将用C#写两个程序;一个是生产者,用于发送一个简单消息;一个是消费者,用于接收消息和把他们打印出来。我们将忽略一些.NET API的详细信息,专注于更简单的开始。这是一个关于"Hello World"简单的小例子。

       在下图中, "P"是我们的消息生产者,"C"是我们消息的消费者。在中间的红色矩形框代表一个队列,也就是消息的缓冲区,RabbitMQ代表是消息的消费者。

        (P) -> [|||] -> (C)



       Net客户端类库

         RabbitMQ支持多种协议,本教程使用AMQP 0-9-1,这是一个针对消息的开放的、通用的协议。RabbitMQ使用了多种语言开发了针对不同环境的客户端。下面我们将使用由RabbitMQ提供的Net客户端。

        这个客户端类库支持.NET Core以及.NET Framework 4.5.1 以上的版本。本教程将使用.NET Core,以便确保您安装在您的路径中。

        你也可以使用 Net Framework 来完成本实例,只是安装步骤有些不同而已。

        RabbitMQ的客户端类库已经部署到了NuGet上,并且您可以通过NuGet下载和使用。

        本教程假定您正在使用Windows PowerShell。


    三、安装

       首先让我们确认您已经有了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

       这将生成两个目录,一个目录是Send,另一个目录是Receive.

       然后我们增加客户端的依赖

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

      现在我们已经有了两个项目安装完毕,可以开始写一些代码了。

    四、发送消息

                (P) -> [|||]

       我们会调用我们的消息发布者(发送者)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())
                   {
                    ...
                  }
               }
           }
        }

        当前connection连接是一个抽象的套接字连接,为我们负责协议版本的协商和认证等。这里我们连接到本地机器上的消息代理--从此处的localhost关键字可以看出是本机。如果我们想连接到另一台机器上的一个消息代理,我们只需在这里指定它的名称或IP地址。

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

        要发送,我们必须声明一个队列,然后我们把消息发送到这个队列里面:

     1  using System;
     2        using RabbitMQ.Client;
     3        using System.Text;
     4 
     5        class Send
     6        {
     7            public static void Main()
     8            {
     9                var factory = new ConnectionFactory() { HostName = "localhost" };
    10                using(var connection = factory.CreateConnection())
    11                using(var channel = connection.CreateModel())
    12                {
    13                    channel.QueueDeclare(queue: "hello",
    14                                  durable: false,
    15                                  exclusive: false,
    16                                  autoDelete: false,
    17                                  arguments: null);
    18 
    19                    string message = "Hello World!";
    20                    var body = Encoding.UTF8.GetBytes(message);
    21 
    22                    channel.BasicPublish(exchange: "",
    23                                  routingKey: "hello",
    24                                  basicProperties: null,
    25                                  body: body);
    26                    Console.WriteLine(" [x] Sent {0}", message);
    27                }
    28 
    29                Console.WriteLine(" Press [enter] to exit.");
    30                Console.ReadLine();
    31            }
    32        }


        声明队列是一次性的,只有当它不存在时才会被创建。消息内容是字节数组,所以您可以编码任何您喜欢的内容。

        当上面的代码完成运行时,通道和连接将被释放。

        发送不成功的解决办法

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


    五、接收消息

         以上就是我们的消息生产者,我们的消息的消费者是从RabbitMQ拉消息,因此不能像我们的消息发布者那样发布单一消息,我们需要保持我们的消费者程序持续运行,并且监听消息,如果有就获取并且打印出来。

        [|||] -> (C)


         Receive.cs文件和Send.cs文件有一些很像的代码需要书写:

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

         消息接收者的设置和消息的发布者一样,我们要打开一个连接和一个通道,并且声明一个从中获取消息的队列,注意这个是和Send.cs文件中的发布者的队列相匹配的。

    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接收事件处理程序所做的。

     1 using RabbitMQ.Client;
     2        using RabbitMQ.Client.Events;
     3        using System;
     4        using System.Text;
     5 
     6        class Receive
     7        {
     8            public static void Main()
     9            {
    10               var factory = new ConnectionFactory() { HostName = "localhost" };
    11               using(var connection = factory.CreateConnection())
    12               using(var channel = connection.CreateModel())
    13               {
    14                    channel.QueueDeclare(queue: "hello",
    15                                  durable: false,
    16                                  exclusive: false,
    17                                  autoDelete: false,
    18                                  arguments: null);
    19 
    20                    var consumer = new EventingBasicConsumer(channel);
    21                    consumer.Received += (model, ea) =>
    22                    {
    23                        var body = ea.Body;
    24                        var message = Encoding.UTF8.GetString(body);
    25                        Console.WriteLine(" [x] Received {0}", message);
    26                    };
    27                   channel.BasicConsume(queue: "hello",   noAck: true,    consumer: consumer);
    28 
    29                    Console.WriteLine(" Press [enter] to exit.");
    30                    Console.ReadLine();
    31                }
    32            }
    33        }


    六、把它放在一起

        打开两个端点。

        运行消费者:
     
           cd Receive

           dotnet run

        然后运行生产者

           cd Send

           dotnet Run

        消费者将要打印消息生产者通过RabbitMQ发布的消息。消费者不能间断,必须保持持续运行,等待新消息的到来。当然也可以通过(Ctrl+C 来停止消费者)

        好了,终于写完了,其实是我翻译的,有翻译不对的地方请谅解。

        原文地址如下:http://www.rabbitmq.com/tutorials/tutorial-one-dotnet.html

  • 相关阅读:
    golang删除数组某个元素
    golang用通道实现信号量,控制并发个数
    什么是ScaleIO中的forwards rebuild和backwards rebuild?
    SQL Server中的database checkpoint
    如何将thick provision lazy zeroed的VMDK文件转换为thick provision eager zeroed?
    LoadTestAgentResultsLateException in VS2010
    SQL Server Instance无法启动了, 因为TempDB所在的分区没有了, 怎么办?
    VMware vCenter中, 如何辩认虚机上Raw Device Mapping过了的一块物理磁盘?
    SQL Server AlwaysOn Setup Step-By-Step Guide
    TPC-E在populate测试Database时需要注意的一些事项
  • 原文地址:https://www.cnblogs.com/PatrickLiu/p/6934745.html
Copyright © 2011-2022 走看看