Three exchange types of RabbitMQ

Posted by kankaro on Fri, 12 Jun 2020 05:58:55 +0200

1, Direct type

1. Schematic overview

As shown in the figure, in this mode, the producer sends messages to the switch in the broker (there can be multiple exchange switches in a broker, and one exchange can be bound to multiple queue queues). The switch distributes the messages to the queue corresponding to the routing key (queue1) according to the routing key (123) carried by the message, because the routing key bound to the queue of queue1 is also 123, so At this time, the consumer 1 listening to queue1 gets the message "Zhang San". That is to say, there is no direct relationship between the consumer and routing key. The consumer only needs to care about which queue to pay attention to.

2. Code implementation
2.1 create a maven project and introduce the following dependencies

  <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.7.3</version>
        </dependency>

2.2 code the message producer

public class Send {

    public static void main(String[] args) throws IOException, TimeoutException {

        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //Create a queue named myqueueDirect
            channel.queueDeclare("myqueueDirect", false, false, false, null);
            //Create another switch
            //Since you must ensure that the switch has been created when sending messages, this line of code is used to create if the switch does not exist or not
            channel.exchangeDeclare("directExchange","direct",true);
            //Binding with queues (myqueueDirect) and switches (directExchange) through routing key (routing direct)
            channel.queueBind("myqueueDirect","directExchange","routing-direct");

            String message = "direct Mode test message";
            //The producer sends a message to the directExchange switch. The routing key carried by the message is routing direct
            channel.basicPublish("directExchange","routing-direct",null,message.getBytes("utf-8"));

            System.out.println("Message sent");
        }catch (Exception e){

        }finally {
            channel.close();
            connection.close();
        }

    }

}

2.3 writing consumer code

public class Consumer {

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //You can create a queue without creating it. If there is no queue, create it. If there is one, discard the creation
            channel.queueDeclare("myqueueDirect", false, false, false, null);
            //Another switch can be created without creation. If there is no switch, it will be created. If there is one, it will be abandoned
            channel.exchangeDeclare("directExchange","direct",true);
            //Binding with queues and switches through routing key
            channel.queueBind("myqueueDirect","directExchange","routing-direct");

            /**
             * Listen to a queue and get the data in the queue
             */
            channel.basicConsume("myqueueDirect",true,"",new DefaultConsumer(channel){
                @Override
                public void handleDelivery(java.lang.String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    java.lang.String message = new java.lang.String(body, "utf-8");
                    System.out.println("Consumer News " + message);
                }
            });

        }catch (Exception e){

        }finally {

        }
    }

}

Run view:

2, Fanout type

1. Schematic overview

The direct mode switch just now needs a routing key when binding a queue. A routing key binds a queue. The fanout mode does not need a routing key, but binds the queue to the switch directly. The consumer can only listen to the queue.

2. Code implementation

2.1 write producer code

public class FanoutSend {
    public static void main(String[] args) throws IOException, TimeoutException {

        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();

            //Send message in fanout mode
            //Define before sending the message to ensure that the switch must exist
            channel.exchangeDeclare("fanoutExchange","fanout",true);

            String message = "fanout Mode test message";

            //There is no need to bind routing key. The second parameter is empty
            channel.basicPublish("fanoutExchange","",null,message.getBytes("utf-8"));

            System.out.println("Message sent");
        }catch (Exception e){

        }finally {
            if (channel != null){
                channel.close();
                connection.close();
            }
        }

    }

}

Since fanout mode is similar to a broadcast mode, two consumers are created to monitor this time

2.2 code consumer 1

public class Consumer {

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //Because fanout is a broadcast mode, there is no need to specify a specific pair of column names, and create a random queue name
            String queueName = channel.queueDeclare().getQueue();
            //Create a switch
            channel.exchangeDeclare("fanoutExchange","fanout",true);
            //fanout mode switch does not need to bind routing key
            channel.queueBind(queueName,"fanoutExchange","");

            //Consumer listening queue
            channel.basicConsume(queueName,true,"",new DefaultConsumer(channel){
                @Override
                public void handleDelivery(java.lang.String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    java.lang.String message = new java.lang.String(body, "utf-8");
                    System.out.println("fanout: Message accepted by consumer 1 " + message);
                }
            });

        }catch (Exception e){

        }finally {

        }
    }

}

2.3 code consumer 2

public class Consumer2 {

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //Create a random queue name
            String queueName = channel.queueDeclare().getQueue();
            //Create a switch
            channel.exchangeDeclare("fanoutExchange","fanout",true);
            //fanout mode switch does not need to bind routing key
            channel.queueBind(queueName,"fanoutExchange","");

            /**
             * Listen to a queue and get the data in the queue
             */
            channel.basicConsume(queueName,true,"",new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("fanout: Message accepted by consumer 2 " + message);
                }
            });

        }catch (Exception e){

        }finally {

        }
    }
    
}

Note: you must start two consumers first, otherwise if you start the producer first, the consumer will not be able to consume the message sent by the producer.

Run view:


It can be seen that fanout mode does not need to bind routing key to messages when sending messages. It only needs to send messages to the specified switch. The exchange opportunity will send the messages to all bound queues.

3, Topic

1. Schematic overview

The topic type switch uses wildcards to dynamically send messages to the corresponding queues,
This mode needs to execute routing key when the switch and the queue are bound, where "*" must match one word and "ා" must match 0 or more words. (1) If the routing key carried by the message is AA, the message will be sent to queue1 and queue3, because the routing key bound by queue2 is AA. *, that is, there must be a word after AA. (2) If the routing key carried by the message is aa.123, the message will be sent to queue2 and queue3, because the routing key bound by queue1 is AA, that is to say, it can only match the routing key equal to AA. (3) If the routing key carried by the message is aa.123.bb, the message will be sent to queue3, because the routing key bound by queue1 can only match the one with routing key equal to AA. The routing key of queue2 binding can only match one word, while AA. ා can match 0 or more words.

2. Code implementation

2.1 write producer code (the first test routing key is aa)

public class TopicSend {

    public static void main(String[] args) throws IOException, TimeoutException {

        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();

            //Send message in fanout mode
            //Before sending a message, it's best to define it to ensure that the switch must exist
            channel.exchangeDeclare("topicExchange","topic",true);

            String message = "topic Mode test message";

            //You need to bind the routing key, and only send messages to the queues that meet the routing key rules
            channel.basicPublish("topicExchange","aa",null,message.getBytes("utf-8"));

            System.out.println("Message sent");
        }catch (Exception e){

        }finally {
            if (channel != null){
                channel.close();
                connection.close();
            }
        }

    }

}

2.2 write the consumer code of the queue with routing key matching "aa"

public class Consumer {

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //Create queue
            channel.queueDeclare("topicQueue",true,false,false,null);
            //Create another switch
            channel.exchangeDeclare("topicExchange","topic",true);
            //Binding the routing key to bind the queue to the switch
            channel.queueBind("topicQueue","topicExchange","aa");

            /**
             * Listen to a queue and get the data in the queue
             */
            channel.basicConsume("topicQueue",true,"",new DefaultConsumer(channel){
                @Override
                public void handleDelivery(java.lang.String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    java.lang.String message = new java.lang.String(body, "utf-8");
                    System.out.println("topic: Consumer 1(aa)Messages received " + message);
                }
            });

        }catch (Exception e){

        }finally {

        }
    }

}

2.3 write the consumer code of the queue with routing key matching "aa. *"

public class Consumer2 {

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //Create queue
            channel.queueDeclare("topicQueue2",true,false,false,null);
            //Create another switch
            channel.exchangeDeclare("topicExchange","topic",true);
            //Binding the routing key to bind the queue to the switch
            channel.queueBind("topicQueue2","topicExchange","aa.*");

            /**
             * Listen to a queue and get the data in the queue
             */
            channel.basicConsume("topicQueue2",true,"",new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("topic: Consumer 2( aa.* )Messages received " + message);
                }
            });

        }catch (Exception e){

        }finally {

        }
    }

}

2.4 write the consumer code of the queue with routing key matching "aa. ×"

public class Consumer3 {

    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure link information
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");

        Connection connection = null; //Define connections
        Channel channel = null; //Defining channels

        try {
            connection = connectionFactory.newConnection();
            channel = connection.createChannel();
            //Create queue
            channel.queueDeclare("topicQueue3",true,false,false,null);
            //Create another switch
            channel.exchangeDeclare("topicExchange","topic",true);
            //Binding the routing key to bind the queue to the switch
            channel.queueBind("topicQueue3","topicExchange","aa.#");

            /**
             * Listen to a queue and get the data in the queue
             */
            channel.basicConsume("topicQueue3",true,"",new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String message = new String(body, "utf-8");
                    System.out.println("topic: Consumer 3( aa.# )Messages received“ + message);
                }
            });

        }catch (Exception e){

        }finally {

        }
    }

}

The producer sends a message and runs to view:

As you can see, only the two queues, topicQueue and topicQueue3, received the message, because aa matched the routing key (aa and aa.?) of the two queues.

Change the routing key of the production message to aa.123

The producer sends a message and runs to view:

As you can see, only the two queues, topicque2 and topicque3, received messages, because aa.123 matched the routing key (AA. * and AA. ා) of the two queues.

Change the routing key of the production message to aa.123.bb

The producer sends a message and runs to view:

As you can see, only the queue of topicque3 receives messages, because aa.123.bb matches the routing key (AA. ා) of the queue.

Topics: Java Maven RabbitMQ