RabbitMQ Introduction: Topic Exchange

Posted by fahim_junoon on Sun, 12 May 2019 09:50:19 +0200

In our last blog post, we used direct exchange instead of fanout exchange. This time, let's look at topic exchange.

Introduction to Topic Exchange

Topic exchange is similar to direct exchange in that it matches routing key and binding key, but topic exchange can set multiple criteria for routing key.

direct routers are similar to exact queries in sql statements; topic routers are somewhat similar to fuzzy queries in sql statements.

Do you remember? We are in the " RabbitMQ Introduction: Publish/Subscribe > The classification of exchange is introduced.

Direct: Delivery is based entirely on key. For example, when routing key is set to "abc" at binding time, messages submitted by clients will only be delivered to the queue if key is set to "abc".
Topic: The key is delivered after pattern matching. Symbol "" matches one or more words. Symbol "*" matches exactly one word. For example, "abc. " matches "abc.def.ghi", "abc. *" only matches "abc.def".
Fanout: No key is required. It takes a broadcast mode, and when a message comes in, it is delivered to all queues bound to the switch.
Headers: We can ignore it.

Below is the working model given by the official website (P for producer, X for exhange, red Q for queue, C for consumer):

Let's analyze this model.

It sends messages to describe animals. Routing keys have three words: <speed>. <color>. <species>. The first word describes speed, the second describes color, and the third describes species.
There are three binding keys, Q1 binding key is *. orange. * (focus on all animals with orange color); Q2 binding key has two, namely *. *. rabbit (focus on all rabbits) and lazy. # (focus on all animals with lazy speed).

Therefore, messages with the routing key quick.orange.rabbit will be sent to Q1 and Q2, messages with the routing key quick.orange.fox will be sent to Q1, and messages with the routing key lazy.brown.fox will be sent to Q2. The message with the routing key lazy.pink.rabbit will be sent to Q2, but note that it only reaches Q2 once, although it matches two binding keys. Messages with the routing key quick.brown.fox will be discarded because they do not match any binding key.

What if someone shakes four words like lazy.orange.male.rabbit? Because it matches lazy. #, it will be sent to Q2.

Code examples

Now let's look at the code.

  1. Producer
    public class LogTopicSender {
        // exchange Name
        public static String EXCHANGE_NAME = "topicExchange";
    
        public static void main(String[] args) {
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            Connection connection = null;
            Channel channel = null;
            try {
                // 1.Create connections and channels
                connection = factory.newConnection();
                channel = connection.createChannel();
    
                // 2.Statement for channels topic Type exchange
                channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
                
                // 3.Send a message to the specified exchange,Queue specified as empty,from exchange Determine which queues to send depending on the situation
                String routingKey = "info";
    //            String routingKey = "log4j.error";
    //            String routingKey = "logback.error";
    //            String routingKey = "log4j.warn";
                String msg = " hello rabbitmq, I am " + routingKey;
                channel.basicPublish(EXCHANGE_NAME, routingKey, null, msg.getBytes());
                System.out.println("product send a msg: " + msg);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            } finally {
                // 4.Close connection
    
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    }

     

  2. Consumer
    public class LogTopicReciver {
    
        public static void main(String[] args) {
            ConnectionFactory factory = new ConnectionFactory();
            factory.setHost("localhost");
            Connection connection = null;
            Channel channel = null;
            try {
                // 1.Create connections and channels
                connection = factory.newConnection();
                channel = connection.createChannel();
    
                // 2.Statement for channels topic Type exchange
                channel.exchangeDeclare(LogTopicSender.EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
                // 3.Create queues with random names
                String queueName = channel.queueDeclare().getQueue();
    
                // 4.establish exchange Binding relationship with queues
                String[] bindingKeys = { "#" };
    //            String[] bindingKeys = { "log4j.*", "#.error" };
    //            String[] bindingKeys = { "*.error" };
    //            String[] bindingKeys = { "log4j.warn" };
                for (int i = 0; i < bindingKeys.length; i++) {
                    channel.queueBind(queueName, LogTopicSender.EXCHANGE_NAME, bindingKeys[i]);
                    System.out.println(" **** LogTopicReciver keep alive ,waiting for " + bindingKeys[i]);
                }
    
                // 5.Generate and monitor consumers through callbacks
                Consumer consumer = new DefaultConsumer(channel) {
                    @Override
                    public void handleDelivery(String consumerTag, Envelope envelope,
                            com.rabbitmq.client.AMQP.BasicProperties properties, byte[] body) throws IOException {
    
                        // Get the message content and process it
                        String msg = new String(body, "UTF-8");
                        System.out.println("*********** LogTopicReciver" + " get message :[" + msg + "]");
                    }
                };
                // 6.Consumer News
                channel.basicConsume(queueName, true, consumer);
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    }

     

  3. Start consumers as consumers 1
  4. Change String[] bindingKeys = {""}; to String[] bindingKeys = {"log4j. *", "#. error"}; / String[] bindingKeys = {"*. error"}; / String[] bindingKeys = {"log4j. warn}; and then start as Consumer 2, Consumer 3, and Consumer 4.
  5. Start four producers, routing key is String routing key = info; String routing key = log4j. error; String routing key = logback. error; String routing key = log4j. warn;
  6. Observing console log
    Producer:
    product send a msg:  hello rabbitmq, I am info
    product send a msg:  hello rabbitmq, I am log4j.error
    product send a msg:  hello rabbitmq, I am logback.error
    product send a msg:  hello rabbitmq, I am log4j.warn
    
    //Consumer 1:
     **** LogTopicReciver keep alive ,waiting for #
    *********** LogTopicReciver get message :[ hello rabbitmq, I am info]
    *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.error]
    *********** LogTopicReciver get message :[ hello rabbitmq, I am logback.error]
    *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.warn]
    
    //Consumer 2:
     **** LogTopicReciver keep alive ,waiting for log4j.*
     **** LogTopicReciver keep alive ,waiting for #.error
    *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.error]
    *********** LogTopicReciver get message :[ hello rabbitmq, I am logback.error]
    *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.warn] //Consumer 3: **** LogTopicReciver keep alive ,waiting for *.error *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.error] *********** LogTopicReciver get message :[ hello rabbitmq, I am logback.error] //Consumer 4: **** LogTopicReciver keep alive ,waiting for log4j.warn *********** LogTopicReciver get message :[ hello rabbitmq, I am log4j.warn]

     

  7. Watch RabbitMQ Management Page

     

Topics: Java log4j RabbitMQ SQL