设为首页 收藏本站
查看: 1218|回复: 0

[经验分享] RabbitMQ系列教程之四:路由(Routing)

[复制链接]

尚未签到

发表于 2017-12-9 16:44:36 | 显示全部楼层 |阅读模式
  (使用Net客户端)

在上一个教程中,我们构建了一个简单的日志系统,我们能够向许多消息接受者广播发送日志消息。

在本教程中,我们将为其添加一项功能 ,这个功能是我们将只订阅消息的一个子集成为可能。 例如,我们可以只将关键的错误消息输出到日志文件(以节省磁盘空间),同时仍然可以在控制台上打印所有日志消息。

1、绑定

在以前的例子中,我们已经创建了绑定。 你可能会记得如下代码:





channel.QueueBind(queue: queueName, exchange: "logs", routingKey: "");
  
【绑定】是【消息交换机】和【队列】之间的关系纽带,通过绑定把二者关联起来。 这可以简单地理解为:队列可以接收来自此【消息交换机】的消息。

【绑定】可以占用额外的路由选择参数。 为了避免与BasicPublish参数混淆,我们将其称为【绑定键】。 以下代码就是如何用一个键值来创建一个绑定:





channel.QueueBind(queue: queueName,
exchange: "direct_logs",
routingKey: "black");
  
【绑定键】的含义取决于交换类型。 以前我们使用的【Fanout】类型的【消息交换机】忽略了它的取值。

2、直接交换

   在上一个教程中,我们的日志记录系统向所有【消费者】发送所有消息。 我们希望将其扩展为允许基于其严重性过滤消息。 例如,我们可能希望将写入磁盘日志消息的脚本仅接受严重错误,而不会在警告或信息日志消息上浪费磁盘空间。

   我们正在使用一个【Fanout】类型的【消息交换机】,它不会给我们带来很大的灵活性 - 它只能无意识地发送。

   我们将使用一个【Direct】类型的【消息交换机】。 直接转换路由的背后的算法其实是很简单的 - 把消息传递到【绑定键 binding key】和消息的【路由键 routing key】完全匹配的队列中。

   为了说明,请考虑以下设置:

       DSC0000.png

   在这个设置中,我们可以看到【Direct】类型的【消息交换机】X与两个队列相绑定。 第一个队列与【绑定键】的值是Orange相绑定的,第二个队列有两个绑定,一个【绑定键】的值是black,另一个【绑定键】的值是green。

   在这样的设置中,发布到具有【路由键】为orange的【消息交换机】的消息将被路由到队列Q1。 具有black或green【路由键】的消息将转到Q2。 所有其他消息将被丢弃。


3、多重绑定


       DSC0001.png   使用相同的【绑定键】绑定多个队列是完全合法的。 在我们的示例中,我们可以在X和Q1之间添加【绑定键】是black的绑定。 在这种情况下,【direct】类型的【消息交换机】将表现得像【Fanout】类型的【消息交换机】,并将消息发送到所有匹配的队列。 具有【路由键】是black的消息将传送到Q1和Q2。


4、发出日志

   我们将发送消息到【Direct】类型的【消息交换机】来替换【fanout】类型的【消息交换机】,在我们现在的日志系统将使用此模型。 我们将提供日志严重性作为【路由键】。 这样接收脚本就能够选择想要接收的严重性。 我们首先关注发出日志。

   像以前一样,我们首先要建立一个【消息交换机】:



channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
  现在,我们准备发送消息:



var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "direct_logs",
routingKey: severity,
basicProperties: null,
body: body);
  
    为了简化事情,我们假设“严重性”可以是“信息”,“警告”,“错误”之一。

5、订阅

   接收消息将像上一个教程一样工作,除了一个例外 - 我们将为每个我们感兴趣的严重性创建一个新的绑定。



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

      DSC0002.png

  以下是EmitLogDirect.cs类的代码:



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

class EmitLogDirect
{
     public static void Main(string[] args)
     {
         var factory = new ConnectionFactory() { HostName = "localhost" };
         using(var connection = factory.CreateConnection())
         using(var channel = connection.CreateModel())
         {
             channel.ExchangeDeclare(exchange: "direct_logs",
                                     type: "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 '{0}':'{1}'", severity, message);
         }

         Console.WriteLine(" Press [enter] to exit.");
         Console.ReadLine();
     }
}
  
以下是ReceiveLogsDirect.cs类的代码:



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

class ReceiveLogsDirect
{
     public static void Main(string[] args)
     {
         var factory = new ConnectionFactory() { HostName = "localhost" };
         using(var connection = factory.CreateConnection())
         using(var channel = connection.CreateModel())
         {
             channel.ExchangeDeclare(exchange: "direct_logs",
                                     type: "direct");
             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;
                     var message = Encoding.UTF8.GetString(body);
                     var routingKey = ea.RoutingKey;
                     Console.WriteLine(" [x] Received '{0}':'{1}'",
                                       routingKey, message);
                 };
                 channel.BasicConsume(queue: queueName,
                                      noAck: true,
                                      consumer: consumer);

                 Console.WriteLine(" Press [enter] to exit.");
                 Console.ReadLine();
             }
         }
    }
      
    如果您只想将“警告”和“错误”(而不是“信息”)保存到文件中,只需打开控制台并键入:





    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
      
    而且,例如,要发出错误日志消息,只需键入:





    cd EmitLogDirect
    dotnet run error "Run. Run. Or it will explode."
    # => [x] Sent 'error':'Run. Run. Or it will explode.'
      
    以下是原文地址:http://www.rabbitmq.com/tutorials/tutorial-four-dotnet.html
      今天这篇文章终于翻译完了,整个系列还有几篇没翻译。英文水平有限,错误在所难免,欢迎大家提出来,共同学习。

  • 运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
    2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
    3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
    4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
    5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
    6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
    7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
    8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

    所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-422464-1-1.html 上篇帖子: RabbitMQ镜像模式双节点部署时故障转移过程中队列中消息的状态 下篇帖子: Windows远程连接Ubuntu服务器
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    扫码加入运维网微信交流群X

    扫码加入运维网微信交流群

    扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

    扫描微信二维码查看详情

    客服E-mail:kefu@iyunv.com 客服QQ:1061981298


    QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


    提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


    本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



    合作伙伴: 青云cloud

    快速回复 返回顶部 返回列表