rabbitMQ_topic(五)

 

主题转发器

发送到主题转发器的消息不能有任意的 routing_key - 它必须是由点分隔的单词列表。这些单词可以是任何东西,但通常它们指定与消息相关联的一些功能。几个有效的routeKey示例:“ stock.usd.nyse”,“ nyse.vmw ”,“ quick.orange.rabbit ”。routeKey中可以有任意多的单词,最多可达255个字节。

绑定键(即绑定时使用的routeKey)也必须是相同的形式。topics转发器可以是用通配符:

  • *(星)可以替代一个单词。
  • #(哈希)可以替换零个或多个单词。

如下图:

在这个例子中,我们将发送所有描述动物的消息。消息将使用由三个字(两个点)组成的routeKey发送。routeKey中的第一个单词将描述速度,第二个描述颜色,第三个描述种类( <speed>.<color>.<species>)。

我们创建了三个绑定:Q1队列绑定键* .orange.*,Q2绑定键*.*.rabbit和lazy.#。

这些绑定可以总结为:

  • Q1对所有的橙色动物感兴趣。
  • Q2想听听有关兔子的一切,以及关于懒惰动物的一切。

将routeKey设置为“ quick.orange.rabbit ”的消息将传递给两个队列。消息“ lazy.orange.elephant ”也会传递给两个队列。“ quick.orange.fox ”只会转到第一个队列,而“ lazy.brown.fox ”只能到第二个队列。“ lazy.pink.rabbit ”将被传递到第二个队列。“ quick.brown.fox ”不匹配任何绑定,因此它将被丢弃。

如果我们不按套路出牌,发送一个或四个字的消息,如“ orange ”或“ quick.orange.male.rabbit ”,会发生什么?那么这些消息将不会匹配任何绑定,并将丢失。

但是在某种情况下,如“ lazy.orange.male.rabbit ”即使它有四个单词,却会匹配最后的绑定,并将消息传递到第二个队列。

主题转发器

主题转发是强大的,其他转发器能做到的事情,它也能做到。

当队列与“ # ”(哈希)绑定键绑定时,它将接收所有消息,而不管绑定键是什么,就像fanout转发器一样

当特殊字符“ * ”(星号)和“ # ”(哈希)在绑定中不被使用时,主题转发器将表现得像一个直接转发器。

完整示例

EmitLogTopic.java的代码:

 1 package com.rabbitMQ;
 2 
 3 import com.rabbitmq.client.Channel;
 4 import com.rabbitmq.client.Connection;
 5 import com.rabbitmq.client.ConnectionFactory;
 6 
 7 public class EmitLogTopic {
 8 
 9     private static final String EXCHANGE_NAME = "topic_logs";
10 
11     public static void main(String[] argv)
12                   throws Exception {
13 
14         ConnectionFactory factory = new ConnectionFactory();
15         factory.setHost("localhost");
16         Connection connection = factory.newConnection();
17         Channel channel = connection.createChannel();
18 
19         channel.exchangeDeclare(EXCHANGE_NAME, "topic");
20 
21         String routingKey = getRouting(argv);
22         String message = getMessage(argv);
23 
24         channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
25         System.out.println(" [x] Sent '" + routingKey + "':'" + message + "'");
26 
27         connection.close();
28     }
29    
30     
31     private static String getRouting(String[] argv) {
32 
33         if (argv.length == 0) {
34 
35             return "jr;;p.critical";
36         }
37         String str = argv[0];
38 
39         String routeKey = str.replaceAll("=.*", "");
40 
41         return routeKey;
42     }
43 
44     private static String getMessage(String[] argv) {
45         if (argv.length == 0) {
46 
47             return "I like play game.";
48         }
49         String str = argv[0];
50         String message = str.replaceAll(".*=", "");
51         return message;
52     }
53 
54     
55 }

ReceiveLogsTopic.java的代码:

 1 package com.rabbitMQ;
 2 
 3 import java.io.IOException;
 4 
 5 import com.rabbitmq.client.AMQP;
 6 import com.rabbitmq.client.Channel;
 7 import com.rabbitmq.client.Connection;
 8 import com.rabbitmq.client.ConnectionFactory;
 9 import com.rabbitmq.client.Consumer;
10 import com.rabbitmq.client.DefaultConsumer;
11 import com.rabbitmq.client.Envelope;
12 
13 public class ReceiveLogsTopic {
14   private static final String EXCHANGE_NAME = "topic_logs";
15 
16   public static void main(String[] argv) throws Exception {
17     ConnectionFactory factory = new ConnectionFactory();
18     factory.setHost("localhost");
19     Connection connection = factory.newConnection();
20     Channel channel = connection.createChannel();
21 
22     channel.exchangeDeclare(EXCHANGE_NAME, "topic");
23     String queueName = channel.queueDeclare().getQueue();
24 
25     if (argv.length < 1) {
26       System.err.println("Usage: ReceiveLogsTopic [binding_key]...");
27       System.exit(1);
28     }
29 
30     for (String bindingKey : argv) {
31       channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
32     }
33 
34     System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
35 
36     Consumer consumer = new DefaultConsumer(channel) {
37       @Override
38       public void handleDelivery(String consumerTag, Envelope envelope,
39                                  AMQP.BasicProperties properties, byte[] body) throws IOException {
40         String message = new String(body, "UTF-8");
41         System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
42         System.out.println(consumerTag);//amq.ctag-yqB24qMf7hEtpyZgR1p4MQ
43         System.out.println(properties);//#contentHeader<basic>(content-type=null, content-encoding=null, headers=null, delivery-mode=null, priority=null, correlation-id=null, reply-to=null, expiration=null, message-id=null, timestamp=null, type=null, user-id=null, app-id=null, cluster-id=null)
44         System.out.println(envelope);//Envelope(deliveryTag=1传送标志, redeliver=false重新传送, exchange=topic_logs转发器名称, routingKey=jr;;p.critical)
45       }
46     };
47     channel.basicConsume(queueName, true, consumer);
48   }
49 }

启动ReceiveLogsTopic.java,给它传*.error

启动ReceiveLogsTopic.java,给它传*.info

启动EmitLogTopic.java,给它传#=all matches

结果:俩个ReceiveLogsTopic.java会收到all matches

启动ReceiveLogsTopic.java,给它传mistake=error

只有第一个ReceiveLogsTopic.java收到消息

原文地址:https://www.cnblogs.com/honger/p/6964053.html