Rabbitmq教程翻译(五)Topics主题

主题

(使用Java客户端)

   在 前面的教程中, 我们改进了我们的日志系统。而不是使用一个 交换(fanout exchange)只能够虚拟的广播,我们用了一个 直接交换(direct exchange) ,并获得了一种可能,选择性地接收日志。
   虽然使用直接交换,改进了我们的系统,它仍然有它的局限性-它不能做基于多个标准的路由

    在我们的记录系统中,我们可能想订阅不仅根据严重性的日志,还可以根据源发出日志。你可能知道这个概念从UNIX 系统日志工具,它记录路由基于两严重性(信息/警告/暴击...)和设备(AUTH / cron/ KERN ...)。

    这会给我们很大的灵活性 - 我们可能想听听来自通过“cron”也是从"kern"来的所有日志的严重错误。

    为了实现我们的测井系统,我们需要了解一个更复杂的话题交换(topic exchange)。

主题交流

  发送到一个主题交换的消息不能有任意 routing_key的 -它必须是一个单词列表,以点分隔。这句话可以是任何东西,但他们通常指定连接到该消息的某些功能。一些有效的路由主要例子:“ stock.usd.nyse “,”nyse.vmw “,” quick.orange.rabbit “。有很多的话可以在路由的关键,只要你喜欢,高达255字节的限制。

绑定键(bingding key)也必须以同样的形式。话题交换背后的逻辑 是类似于一个直接交换 -一个消息发送给特定的路由键(routing key)将被传递到所有队列匹配结合键约束。然而,有两个重要的特殊情况,绑定键(banding keys):

  • * (star) can substitute for exactly one word.
  • # (hash) can substitute for zero or more words.

  • 这是最简单的一个例子解释:

    在这个例子中,我们将发送描述动物的消息。该消息将被发送一个路由键包含三个字(两个点)。在路由键将第一个字形容速度快,第二个颜色和第三物种:“ 兼容的<speed>.<colour>.<species> “。

    我们创建了三个绑定:Q1势必具有约束力键“ *.orange.* “和Q2与” *.*.rabbit “和” lazy.# “。

    这些绑定可以概括为:

  • Q1是感兴趣的所有橙色的动物。
  • Q2希望听到所有关于兔子,一切有关懒惰的动物。

  • 具有路由键设置为“ quick.orange.rabbit “ 一则消息将被传递到两个队列。还将消息“ lazy.orange.elephant “他们都去。另一方面“ quick.orange.fox “只会去到第一队列,的” lazy.brown.fox “第二只。将被交付“ lazy.pink.rabbit “第二队列只有一次,即使它匹配两个绑定。“ quick.brown.fox “不匹配任何有约束力的,所以它会被丢弃。


    如果我们打破我们的合同,并发送带有一个或四个字,如“ 橙色 “或” quick.orange.male.rabbit “,会发生什么事?那么,这些消息将不会匹配任何绑定,将会丢失。


    另一方面“ lazy.orange.male.rabbit “,即使它有四个词,将匹配最后的绑定,将被传递到第二队列。


    主题交流


    主题交流是强大的,可以像其他交易所。


    当队列“ # “(哈希)结合键绑定-将收到的所有邮件,不管扇交换路由键-像。


    当特殊字符“ * “(星号)和” # “(井)不使用绑定的话题交换行为就像一个直接的。


    全部放在一起


    我们要在我们的记录系统使用一个话题交换。我们会启动关闭与工作假设日志将路由键有两句话:“ <facility> <severity> “。


    该代码是在前面的教程中几乎是一样的 。具有路由键设置为“ quick.orange.rabbit “ 一则消息将被传递到两个队列。还将消息“lazy.orange.elephant “他们都去。另一方面“ quick.orange.fox “只会去到第一队列,的”lazy.brown.fox “第二只。将被交付“ lazy.pink.rabbit “第二队列只有一次,即使它匹配两个绑定。“quick.brown.fox “不匹配任何有约束力的,所以它会被丢弃。
  • 如果我们打破我们的合同,并发送带有一个或四个字,如“ 橙色 “或” quick.orange.male.rabbit “,会发生什么事那么,这些消息将不会匹配任何绑定,将会丢失。

    另一方面“ lazy.orange.male.rabbit “,即使它有四个词,将匹配最后的绑定,将被传递到第二队列。

    主题交流

    主题交流是强大的,可以像其他交易所。

    当队列“  “(哈希)结合键绑定-将收到的所有邮件,不管交换路由键-像。

    当特殊字符“ * “(星号)和”  “(井)不使用绑定的话题交换行为就像一个直接的。

    全部放在一起

    我们要在我们的记录系统使用一个话题交换。我们会启动关闭与工作假设日志将路由键有两句话:“<facility> <severity> “。

    该代码是在前面的教程中几乎是一样的 。

     EmitLogTopic.java的代码:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class EmitLogTopic {
    
        private static final String EXCHANGE_NAME = "topic_logs";
    
        public static void main(String[] argv)
                      throws Exception {
    
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.exchangeDeclare(EXCHANGE_NAME, "topic");
    
            String routingKey = getRouting(argv);
            String message = getMessage(argv);
    
            channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
            System.out.println(" [x] Sent '" + routingKey + "':'" + message + "'");
    
            connection.close();
        }
        //...
    }
    

    ReceiveLogsTopic.java的代码:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    public class ReceiveLogsTopic {
    
        private static final String EXCHANGE_NAME = "topic_logs";
    
        public static void main(String[] argv)
                      throws Exception {
    
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            Connection connection = factory.newConnection();
            Channel channel = connection.createChannel();
    
            channel.exchangeDeclare(EXCHANGE_NAME, "topic");
            String queueName = channel.queueDeclare().getQueue();
    
            if (argv.length < 1){
                System.err.println("Usage: ReceiveLogsTopic [binding_key]...");
                System.exit(1);
            }
    
            for(String bindingKey : argv){
                channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
            }
    
            System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
    
            QueueingConsumer consumer = new QueueingConsumer(channel);
            channel.basicConsume(queueName, true, consumer);
    
            while (true) {
                QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                String message = new String(delivery.getBody());
                String routingKey = delivery.getEnvelope().getRoutingKey();
    
                System.out.println(" [x] Received '" + routingKey + "':'" + message + "'");
            }
        }
    }

    运行下面的例子,包括在classpath 教程1 -在Windows上,使用%CP%。

    要接收所有的日志:

    $ java -cp $CP ReceiveLogsTopic "#"


    要接收设施““ 的所有日志:

    $ java -cp $CP ReceiveLogsTopic "kern.*"
    

    或者,如果你想听到关于 "critical"的日志:

    $ java -cp $CP ReceiveLogsTopic "*.critical"
    

    您可以创建多个绑定:

    $ java -cp $CP ReceiveLogsTopic "kern.*" "*.critical"
    

    发出日志与一个路由键(routing key)“ kern.critical “的类型:

    $ java -cp $CP EmitLogTopic "kern.critical" "A critical kernel error"
    

    玩得开心玩这些程序。请注意,代码不作任何假设路由或绑定键,你可能想发挥两个以上路由的关键参数。

    一些玩笑:

    • “ * “的绑定将赶上一个空路由密钥发送的消息?
    • 将“ #* “抓的消息字符串” “ 作为一个关键呢?它会赶上一个字键的消息? 
    • 不同的是“ 一个*# “,从” A# “?

    (完整的源代码为EmitLogTopic.java ReceiveLogsTopic.java

    接下来,找出如何做一个往返消息作为一个远程过程调用教程6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值