• RabbitMQ消息队列(五):Routing 消息路由 2[原]


    上一篇文章使用的是Direct的Exchange,但是没有指定Queue的名字,这样只能是先运行Consumer之后,Producer在运行发消息Consumer才能收到,否则先运行Producer发送消息,在运行Consumer是收不到之前Producer发送的消息,因为Queue的名字像是这样的:amq.gen-X-XSTaseUmil42zrawBVsw都是临时,如果Consumer关闭之后,这个Queue就会自动被RabbitMQ删掉。

    如果想创建可以先执行Producer的Direct的Exchnage呢?因为在实际工作中我们可能需要发送端有消息就会一直发给接收端,不管接收端是否已经运行。如果我们需要指定名称的Queue,并且使用Direct的Exchange方式,我们需要使用Binding的方式。上一篇和第一篇文章中都解释了绑定的含义:绑定其实就是关联了exchange和queue。

    多个routing key指定同一个queue,不管如何指定routing key的名字,发送端发送一次信息,接收端按启动顺序循环执行接收,每次接收一个消息。例子:

    Producer.cs

     1 /// <summary>
     2         /// 多个routing key指定同一个queue
     3         /// 指定Queue的名称,好处就是可以持久化Queue
     4         /// </summary>
     5         /// <param name="args">
     6         /// SendDemo51.exe direct_custom_routing_key_hello1
     7         /// SendDemo51.exe direct_custom_routing_key_hello2
     8         /// 不管如何指定routing key的名字,发送端发送一次信息,接收端按启动顺序循环执行每次接收一个消息。
     9         /// </param>
    10         static void Main(string[] args)
    11         {
    12             if (args.Length < 1)
    13             {
    14                 Console.Error.WriteLine("请指定一个新的Routing Key名称", Environment.GetCommandLineArgs()[0]);
    15                 Environment.ExitCode = 1;
    16                 return;
    17             }
    18             var factory = new ConnectionFactory() { HostName = "localhost" };
    19             using (var connection = factory.CreateConnection())
    20             {
    21                 using (var channel = connection.CreateModel())
    22                 {
    23                     const string EXCHANGE_NAME = "direct_logs";
    24                     channel.ExchangeDeclare(EXCHANGE_NAME, "direct");//Direct :如果 routing key 匹配, 那么Message就会被传递到相应的queue中。
    25 
    26                     const string QUEUE_NAME = "direct_same_queue_name_hello";//使用我们自己指定Queue的名称
    27                     bool durable = true;
    28                     channel.QueueDeclare(QUEUE_NAME, durable, false, false, null);
    29 
    30                     var routingKey = args[0];//指定Routing Key的名称
    31                     channel.QueueBind(QUEUE_NAME, EXCHANGE_NAME, routingKey);//通过绑定将指定的Queue名称、不同的RoutingKey名称使用Direct的Exchange方式进行关联
    32 
    33                     var message = "Hello World! " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    34 
    35                     var body = Encoding.UTF8.GetBytes(message);
    36 
    37                     var properties = channel.CreateBasicProperties();
    38                     properties.SetPersistent(true);//需要持久化Message,即在Publish的时候指定一个properties
    39 
    40                     channel.BasicPublish(EXCHANGE_NAME, routingKey, properties, body);
    41                     Console.WriteLine(" [x] Sent '{0}':'{1}'", routingKey, message);
    42 
    43                     Console.Read();
    44                 }
    45             }
    46         }
    Producer.cs

    Consumer.cs

     1 /// <summary>
     2     /// 多个routing key指定同一个queue
     3     /// 指定Queue的名称,好处就是可以持久化Queue
     4     /// ReceiveDemo51.exe direct_custom_routing_key_hello1
     5     /// ReceiveDemo51.exe direct_custom_routing_key_hello2
     6     /// 不管如何指定routing key的名字,发送端发送一次信息,接收端按启动顺序循环执行每次接收一个消息。
     7     /// </summary>
     8     class Program
     9     {
    10         static void Main(string[] args)
    11         {
    12             if (args.Length < 1)
    13             {
    14                 Console.Error.WriteLine("请指定一个新的Routing Key名称", Environment.GetCommandLineArgs()[0]);
    15                 Environment.ExitCode = 1;
    16                 return;
    17             }
    18             var factory = new ConnectionFactory() { HostName = "localhost" };
    19             using (var connection = factory.CreateConnection())
    20             {
    21                 using (var channel = connection.CreateModel())
    22                 {
    23                     const string EXCHANGE_NAME = "direct_logs";
    24                     channel.ExchangeDeclare(EXCHANGE_NAME, "direct");
    25 
    26                     const string QUEUE_NAME = "direct_same_queue_name_hello";//使用我们自己指定Queue的名称
    27                     bool durable = true;
    28                     channel.QueueDeclare(QUEUE_NAME, durable, false, false, null);
    29 
    30                     string routingKey = args[0];//指定Routing Key的名称
    31                     channel.QueueBind(QUEUE_NAME, EXCHANGE_NAME, routingKey);//通过绑定将指定的Queue名称、不同的RoutingKey名称使用Direct的Exchange方式进行关联
    32                     
    33                     Console.WriteLine(" [*] Waiting for messages. " + "To exit press CTRL+C");
    34 
    35                     var consumer = new QueueingBasicConsumer(channel);
    36                     channel.BasicConsume(QUEUE_NAME, true, consumer);
    37 
    38                     while (true)
    39                     {
    40                         var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
    41 
    42                         var body = ea.Body;
    43                         var message = Encoding.UTF8.GetString(body);
    44                         var routingkey = ea.RoutingKey;
    45                         Console.WriteLine(" [x] Received '{0}':'{1}'", routingkey, message);
    46                     }
    47                 }
    48             }
    49         }
    50     }
    Consumer.cs

     多个Queue关联同一个routing key,多个queue通过routing key可以同时得到发送的内容,例子如下:

    Producer.cs 

     1 /// <summary>
     2         /// 多个Queue关联一个routing key,通过routingkey可以拿到多个queue里面的内容;
     3         /// 如果得到消息的Queue不是指定名称的Queue(此时这个例子是通过routing key得到消息),那么它是不会自动从Queue中删除接收到的消息,
     4         /// 只有是指定名称的Queue收到消息之后才会把Queue中的消息删除。
     5         /// SendDemo52.exe direct_custom_queue_name_hello1
     6         /// SendDemo52.exe direct_custom_queue_name_hello2
     7         /// 发送端发送一次信息,多个接收端同时接收到消息
     8         /// </summary>
     9         /// <param name="args"></param>
    10         static void Main(string[] args)
    11         {
    12             if (args.Length < 1)
    13             {
    14                 Console.Error.WriteLine("请指定一个新的Queue名称", Environment.GetCommandLineArgs()[0]);
    15                 Environment.ExitCode = 1;
    16                 return;
    17             }
    18             var factory = new ConnectionFactory() { HostName = "localhost" };
    19             using (var connection = factory.CreateConnection())
    20             {
    21                 using (var channel = connection.CreateModel())
    22                 {
    23                     const string EXCHANGE_NAME = "direct_logs";
    24                     channel.ExchangeDeclare(EXCHANGE_NAME, "direct");//Direct :如果 routing key 匹配, 那么Message就会被传递到相应的queue中。
    25 
    26                     string queueName = args[0];//得到我们自己指定Queue的名称
    27                     channel.QueueDeclare(queueName, true, false, false, null);
    28 
    29                     const string ROUTING_KEY = "direct_same_routing_key";
    30                     channel.QueueBind(queueName, EXCHANGE_NAME, ROUTING_KEY);//通过绑定将不同的Queue名称、相同的Routing Key名称采用Direct的Exchange方式进行关联
    31 
    32                     var message = "Hello World! " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    33 
    34                     var body = Encoding.UTF8.GetBytes(message);
    35 
    36                     var properties = channel.CreateBasicProperties();
    37                     properties.SetPersistent(true);//需要持久化Message,即在Publish的时候指定一个properties
    38 
    39                     channel.BasicPublish(EXCHANGE_NAME, ROUTING_KEY, properties, body);
    40                     Console.WriteLine(" [x] Sent '{0}':'{1}'", ROUTING_KEY, message);
    41 
    42                     Console.Read();
    43                 }
    44             }
    45         }
    Producer.cs

    Consumer.cs

     1 /// <summary>
     2     /// 多个Queue关联一个routing key,通过routingkey可以拿到多个queue里面的内容;
     3     /// 如果得到消息的Queue不是指定名称的Queue(此时这个例子是通过routing key得到消息),那么它是不会自动从Queue中删除接收到的消息,
     4     /// 只有是指定名称的Queue收到消息之后才会把Queue中的消息删除。
     5     /// ReceiveDemo52.exe direct_custom_queue_name_hello1
     6     /// ReceiveDemo52.exe direct_custom_queue_name_hello2
     7     /// 发送端发送一次信息,多个接收端同时接收到消息
     8     /// </summary>
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             if (args.Length < 1)
    14             {
    15                 Console.Error.WriteLine("请指定一个新的Queue名称", Environment.GetCommandLineArgs()[0]);
    16                 Environment.ExitCode = 1;
    17                 return;
    18             }
    19             var factory = new ConnectionFactory() { HostName = "localhost"  };
    20             using (var connection = factory.CreateConnection())
    21             {
    22                 using (var channel = connection.CreateModel())
    23                 {
    24                     const string EXCHANGE_NAME = "direct_logs";
    25                     channel.ExchangeDeclare(EXCHANGE_NAME, "direct");
    26                     
    27                     string queueName = args[0];//得到我们自己指定Queue的名称
    28                     channel.QueueDeclare(queueName, true, false, false, null);
    29 
    30                     const string ROUTING_KEY = "direct_same_routing_key";
    31                     channel.QueueBind(queueName, EXCHANGE_NAME, ROUTING_KEY);//通过绑定将不同的Queue名称、相同的Routing Key名称采用Direct的Exchange方式进行关联
    32 
    33                     Console.WriteLine(" [*] Waiting for messages. " + "To exit press CTRL+C");
    34 
    35                     var consumer = new QueueingBasicConsumer(channel);
    36                     channel.BasicConsume(queueName, true, consumer);
    37 
    38                     while (true)
    39                     {
    40                         var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
    41 
    42                         var body = ea.Body;
    43                         var message = Encoding.UTF8.GetString(body);
    44                         string routingKeyRe = ea.RoutingKey;
    45                         Console.WriteLine(" [x] Received '{0}':'{1}'", routingKeyRe, message);
    46                     }
    47                 }
    48             }
    49         }
    50     }
    Consumer.cs

    特别注意:

    本例子是支持多个Queue名称同时发送和接收的,Consumer通过routing key可以拿到属于这个routing key里面的多个queue的内容;
    如果Consumer一旦接收到消息,分两种情况:

    1、接收的Consumer不是指定名称的Queue(此时这个Consumer是通过routing key得到Producer发送的消息),那么这个Consumer是不会自动从Queue中删除接收到的消息;

    2、接收的Consumer是指定名称的Queue,那么这个Consumer是会自动从Queue中删除接收到的消息。

    总结:只有当指定名称的Queue收到消息之后才会把Queue中的这条消息删除。

  • 相关阅读:
    好理解的堆排序
    SpringCloud 整合 Python 服务
    SpringCloud入门总结
    Spring异常集中处理和日志集中打印
    Java枚举类型的理解及在后台响应中的使用
    Elasticsearch合并高亮字段
    Elasticsearch分析器结构组成
    Elasticsearch实现英文区分大小写搜索
    Nginx三大功能
    Elasticsearch Java Client 版本区别及起步(5.X 和6.X)
  • 原文地址:https://www.cnblogs.com/qiyebao/p/4205851.html
Copyright © 2020-2023  润新知