5 Topics


Official document address: 5 Topics


Receive messages based on patterns (topics).

Prerequisites

This tutorial assumes that you have installed RabbitMQ and is running on the local host port (5672).

theme

In the previous tutorial, we improved the logging system. We use a directswitch instead of a switch that can only perform analog broadcasts fanout, thereby gaining the possibility of selectively receiving logs.

Although the use of directswitches has improved our system, it still has limitations-it cannot be routed based on multiple conditions.

In our logging system, we may not only want to subscribe to logs based on severity, but also want to subscribe to logs based on the source that issued the log. You may syslogknow this concept from the unix tool , which routes logs according to severity ( info/warn/crit…) and device ( auth/cron/kern…).

This will give us a lot of flexibility-we may want to monitor not only "cron"the error logs from but also "kern"all the logs from.

To achieve this in the logging system, we need to understand more complex topicswitches.

Topic Exchange

The message sent to the topicexchange routing_keymust be a list of words separated by dots. Words can be anything, but usually they specify some characteristics related to the message. Several exemplary efficient routing stock.usd.nysekeys: nyse.vmw, quick.orange.rabbit, . The maximum number 255of bytes for the routing key .

The binding key must also be in the same form. topicThe logic behind the directswitch is similar to that of the switch-messages sent using a specific routing key will be delivered to all queues bound with the matching binding key. However, there are two special cases for binding keys:

  • *Can replace a word.
  • #Can replace zero or more words.

To explain the simplest with an example:


In this example, we will send a message describing an animal. These messages will be sent using a routing key consisting of three words (two dots). The first word in the routing key will describe the speed, the second is the color, and the third is the species:<speed>.<colour>.<species>

We created three bindings: binding Q1with binding key, *.orange.*binding Q2with binding key *.*.rabbitand lazy.#binding.

These bindings can be summarized as:

  • Q1Interested in all orange animals.
  • Q2Interested in rabbits and slow animals.

Set the routing key to the following content, and the corresponding sending queue is as follows:

  • "quick.orange.rabbit"The message with the routing key set to will be sent to two queues.
  • "lazy.orange.elephant"Messages with the routing key set to are also sent to these two queues.
  • "quick.orange.fox"Messages with the routing key set to only go to the first queue.
  • "lazy.brown.fox"Messages with the routing key set to only go to the second queue.
  • "lazy.pink.rabbit"The message with the routing key set to will only be sent to the second queue once, even if it matches two bindings.
  • "quick.brown.fox"The message with the routing key set to does not match any bindings and will therefore be discarded.

If we do not abide by the agreement, with one or four words to convey information, such as "orange"or "quick.orange.mally.rabbit", these messages will not match any binding, will be lost.

"lazy.orange.male.rabbit"On the other hand, even if it has four words, it will match the last binding and will be passed to the second queue.

Topic Exchange

topic Exchange is powerful, just like other exchanges.

When the queue is #bound with a binding key, it will receive all messages, regardless of the routing key, just like in an fanoutexchange.

If the binding key does not use special characters *and #, topicit is the directsame.

Put them together

We will use the topicswitch in the log system . We first assume that the log routing key has two words: <facility>.<severity>.

The code is almost the same as the previous tutorial. EmitLogTopic.javaClass code:

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author wangbo
 * @date 2019/10/23 11:24
 */
public class EmitLogTopic {
    
    
    //交换器名称
    private final static String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        //创建一个连接器连接到服务器
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try(Connection connection = factory.newConnection()){
    
    
            //创建一个通道
            Channel channel = connection.createChannel();
            //声明交换器,设置交换器类型
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
            //从命令行接受参数
            //路由键
            String routingKey = getRouting(args);
            //日志消息
            String message = getMessage(args);
            //发布消息到交换器,并设置路由键
            channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes("UTF-8"));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }

    private static String getRouting(String[] strings) {
    
    
        if (strings.length < 1) {
    
    
            return "anonymous.info";
        }
        return strings[0];
    }

    private static String getMessage(String[] strings) {
    
    
        if (strings.length < 2) {
    
    
            return "Hello World!";
        }
        return joinStrings(strings, " ", 1);
    }

    private static String joinStrings(String[] strings, String delimiter, int startIndex) {
    
    
        int length = strings.length;
        if (length == 0) {
    
    
            return "";
        }
        if (length < startIndex) {
    
    
            return "";
        }
        StringBuilder words = new StringBuilder(strings[startIndex]);
        for (int i = startIndex + 1; i < length; i++) {
    
    
            words.append(delimiter).append(strings[i]);
        }
        return words.toString();
    }
}

ReceiveLogsTopic.javaClass code:

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author wangbo
 * @date 2019/10/22 18:25
 */
public class ReceiveLogsTopic {
    
    
    //交换器名称
    private final static String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        //创建一个连接器连接到服务器
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        //创建一个通道
        Channel channel = connection.createChannel();
        //声明交换器,设置交换器类型
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //获取临时队列的名称
        String queueName = channel.queueDeclare().getQueue();
        //将临时队列和交换器绑定,进行多重绑定
        if (args.length < 1) {
    
    
            System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]");
            System.exit(1);
        }
        for (String bindingKey : args) {
    
    
            channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
        }
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //回调对象
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    
    
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        //消费者监听
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
    
    });
    }
}

Compile and run the example, including 1the classpath from the tutorial -for use on Windows %CP%.

javac -cp $CP ReceiveLogsTopic.java EmitLogTopic.java

Receive all logs:

java -cp $CP ReceiveLogsTopic "#"

Receive all kernlogs from the device :

java -cp $CP ReceiveLogsTopic "kern.*"

Or to receive criticallogs of all levels:

java -cp $CP ReceiveLogsTopic "*.critical"

You can create multiple bindings:

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

Issue kern.criticalthe log with the routing key :

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

Next, 6learn how to perform round-trip messages as a remote procedure call in the tutorial .

Guess you like

Origin blog.csdn.net/wb1046329430/article/details/115289784