RabbitMQ supports message mode

Posted by BuzFortuna on Sat, 09 Oct 2021 04:30:49 +0200

Introduction to the official website

Refer to the official website: https://www.rabbitmq.com/getstarted.html

web interface operation

03-1. Simple mode


Interface operation process: create a queue, enter the default switch, initiate a message to the specified queue, and finally enter the queue for message preview. During preview, you should pay attention to select nack... For preview. If automatic ack is selected, the message will be consumed and the message will be lost.
Note: Although the queue is created without creating a switch, the queue will be automatically bound to a default interactive machine. The switch type is direct. Therefore, when sending messages, you also need to specify the Routing key (just fill in the queue name)


03-2. Work ing mode

web operation viewing video
Switch type: default switch (direct)
Operation process: directly create two queues and enter the default switch to send messages for the two queues respectively (since the interface operation can not intuitively express the mode, it is enough to know)
Features: distribution mechanism

03-3. Publish subscribe mode

web operation viewing video
Switch type: fanout
Operation process: create multiple queues, create a fanout switch, bind the created queue, and then enter the switch to send messages without specifying a routing key. Even if a routing key is specified, it is meaningless. The bound queue can receive messages anyway.
Features: Fanout - publish and subscribe mode. It is a broadcast mechanism. It is a mode without routing key.

03-4. Routing mode

web operation viewing video
Switch type: direct
Operation process: create multiple related queues, create a direct switch, and add binding relationships for it. Note that when adding binding relationships, you need to specify routing key, and then enter the switch to send messages. You need to specify routing key to selectively send messages to the specified queue.
Features: matching mode with routing key
Different from fanout: routing key needs to be specified when adding binding queue in direct, but not in fanout; When direct sends a message, it needs to specify the routing key, while fanout does not. Even if it is specified, it is meaningless.
Note: the default switch also belongs to the direct type. Queues that do not specify the binding relationship will be bound to the default switch by default, and the default switch will automatically assign a routing key to these queues, which is the same as the queue name.

03-5. Topic mode

web operation viewing video
Switch type: topic
Features: fuzzy routing key matching mode, that is, fuzzy matching function is added on the basis of routing mode
Step 1: create a topic type switch, bind the queue and the specified route key (* for matching one or more, # for matching 0 or more)

give an example:
Routing key -------- > queue of received messages
Com.lin.junjie -------- > 3 and 5
Lin.junjie ------------ > 3 and 5
junjie ---------------> 5
Junjie.com ------ > 4 and 5
lin.junjie.com -------> 2,4,5

03-6. Parameter mode

web operation viewing video
Switch type: headers
Features: parameter matching mode, less used, can be ignored.

Code case implementation

01. Publish subscribe mode of RabbitMQ (fanout)


producer

package routing;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 * @author: Learning companion - flying brother
 * @description: Producer Simple queue producer
 * @Date : 2021/3/2
 */
public class Producer {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 6: Prepare to send the contents of the message
            String message = "Hello, learn to accompany!!!";
            String  exchangeName = "fanout_test";
            String routingKey = "";
            // 7: Send a message to the middleware rabbitmq server
            // @params1: switch exchange
            // @params2: queue name / routingkey
            // @params3: property configuration
            // @params4: send message content
            channel.basicPublish(exchangeName, routingKey, null, message.getBytes());
            System.out.println("Message sent successfully!");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

consumer

package routing;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Consumer {
    private static Runnable runnable = () -> {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        //Gets the name of the queue
        final String queueName = Thread.currentThread().getName();
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
            //channel.queueDeclare("queue1", false, false, false, null);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
            finalChannel.basicConsume(queueName, true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println(queueName + ": The message received is:" + new String(delivery.getBody(), "UTF-8"));
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println(queueName + ": Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    };
    public static void main(String[] args) {
        // Start three threads to execute
        new Thread(runnable, "queue2").start();
        new Thread(runnable, "queue3").start();
    }
}

Note: copying and pasting the above code directly may report an error because fanout_test, queue2 and queue3 switches and queues have been created and added binding relationships through the web interface, so they can run the code directly. (you can also create and bind through code, which will be described later)

02. RabbitMQ routing mode (Direct)


producer

package Direct;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 * @author: Learning companion - flying brother
 * @description: Producer Simple queue producer
 * @Date : 2021/3/2
 */
public class Producer {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 6: Prepare to send the contents of the message
            String message = "Hello, learn to accompany!!!";
            String  exchangeName = "direct_test";
            String routingKey1 = "testkey4";
            String routingKey2 = "testkey5";
            // 7: Send a message to the middleware rabbitmq server
            // @params1: switch exchange
            // @params2: queue name / routingkey
            // @params3: property configuration
            // @params4: send message content
            channel.basicPublish(exchangeName, routingKey1, null, message.getBytes());
            channel.basicPublish(exchangeName, routingKey2, null, message.getBytes());
            System.out.println("Message sent successfully!");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

consumer

package Direct;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Consumer {
    private static Runnable runnable = () -> {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        //Gets the name of the queue
        final String queueName = Thread.currentThread().getName();
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
            //channel.queueDeclare("queue1", false, false, false, null);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
            finalChannel.basicConsume(queueName, true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println(queueName + ": The message received is:" + new String(delivery.getBody(), "UTF-8"));
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println(queueName + ": Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    };
    public static void main(String[] args) {
        // Start three threads to execute
        new Thread(runnable, "queue4").start();
        new Thread(runnable, "queue5").start();
    }
}

Note: similarly, you also need to create the switch with this name and the bound routing key value in the interface in advance. (you can also create and bind through code, which will be described later)

03. Topic of RabbitMQ


producer

package topic;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 * @author: Learning companion - flying brother
 * @description: Producer Simple queue producer
 * @Date : 2021/3/2
 */
public class Producer {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 6: Prepare to send the contents of the message
            String message = "Hello, learn to accompany!!!";
            String  exchangeName = "topic_test";
            String routingKey1 = "com.junjie.order";//245 can receive the message
            String routingKey2 = "com.junjie";
            // 7: Send a message to the middleware rabbitmq server
            // @params1: switch exchange
            // @params2: queue name / routingkey
            // @params3: property configuration
            // @params4: send message content
            channel.basicPublish(exchangeName, routingKey1, null, message.getBytes());
            System.out.println("Message sent successfully!");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

consumer

package topic;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Consumer {
    private static Runnable runnable = () -> {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        //Gets the name of the queue
        final String queueName = Thread.currentThread().getName();
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
            //channel.queueDeclare("queue1", false, false, false, null);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
            finalChannel.basicConsume(queueName, true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println(queueName + ": The message received is:" + new String(delivery.getBody(), "UTF-8"));
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println(queueName + ": Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    };
    public static void main(String[] args) {
        // Start three threads to execute
        new Thread(runnable, "queue2").start();
        new Thread(runnable, "queue3").start();
        new Thread(runnable, "queue4").start();
        new Thread(runnable, "queue5").start();
    }
}

Note: the switch, queue and bound routing key s have been defined in advance.

04. Completely declare the relationship between switch and queue through code

producer:

package all;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * @author: Learning companion - flying brother
 * @description: Producer Simple queue producer
 * @Date : 2021/3/2
 */
public class Producer {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();

            //5: Create switches and queues and bind them
            String  exchangeName = "topic_test_junjie";
            channel.exchangeDeclare(exchangeName, "topic");
            channel.queueDeclare("queue6",false, false, false, null);
            channel.queueDeclare("queue7",false, false, false, null);
            channel.queueDeclare("queue8",false, false, false, null);
            //*Match one or more, # match 0 or more
            channel.queueBind("queue6",exchangeName,"*.jun.*");
            channel.queueBind("queue7",exchangeName,"#.jun.*");
            channel.queueBind("queue8",exchangeName,"#.jun.#");


            // 6: Prepare to send the contents of the message
            String message = "Hello, learn to accompany!!!";

            String routingKey1 = "com.jun";//8 can receive messages
            String routingKey2 = "com.lin.jun";//8 can receive messages
            String routingKey3 = "com.lin.jun.jie";//678 can receive the message
            String routingKey4 = "jun.jie";//78 can you get the message
            // 7: Send a message to the middleware rabbitmq server
            // @params1: switch exchange
            // @params2: queue name / routingkey
            // @params3: property configuration
            // @params4: send message content
            channel.basicPublish(exchangeName, routingKey1, null, message.getBytes());
            System.out.println("Message sent successfully!");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Operation results:


consumer:

package all;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Consumer {
    private static Runnable runnable = () -> {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        //Gets the name of the queue
        final String queueName = Thread.currentThread().getName();
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
            //channel.queueDeclare("queue1", false, false, false, null);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
            finalChannel.basicConsume(queueName, true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    System.out.println(queueName + ": The message received is:" + new String(delivery.getBody(), "UTF-8"));
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println(queueName + ": Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    };
    public static void main(String[] args) {
        // Start three threads to execute
        new Thread(runnable, "queue6").start();
        new Thread(runnable, "queue7").start();
        new Thread(runnable, "queue8").start();
    }
}

05. Work mode of RabbitMQ


When there are multiple consumers, which consumer will consume our news, and how can we balance the amount of consumer consumption information?
There are two main modes:
1. Distribution in polling mode: one for each consumer, distributed equally;
2. Fair distribution: fair distribution is carried out according to the consumption capacity of consumers, with more fast processing and less slow processing; Distribution according to work;

Work mode - round robin

Switch type: default
Features: when multiple consumers access the message, the message distribution mode is that each consumer allocates one message in turn until the message consumption is completed;
producer:

package work;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 * @author: Learning companion - flying brother
 * @description: Producer Simple queue producer
 * @Date : 2021/3/2
 */
public class Producer {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 6: Prepare to send the contents of the message
            //===============================end topic mode==================================
            for (int i = 1; i <= 20; i++) {
                //Content of the message
                String msg = "Learning companion:" + i;
                // 7: Send a message to the middleware rabbitmq server
                // @params1: switch exchange
                // @params2: queue name / routingkey
                // @params3: property configuration
                // @params4: send message content
                channel.basicPublish("", "queue1", null, msg.getBytes());
            }
            System.out.println("Message sent successfully!");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Consumer 1:

package work;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Work1 {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("consumer-Work1");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
//            channel.queueDeclare("queue1", false, false, false, null);
            // At the same time, the server will only push one message to the consumer (it does not work for polling)
              // finalChannel.basicQos(1);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
         
            finalChannel.basicConsume("queue1", true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    try{
                        System.out.println("Work1-The message received is:" + new String(delivery.getBody(), "UTF-8"));
                        Thread.sleep(2000);
                    }catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println("Work1-Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Consumer 2:

package work;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Work2 {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("consumer-Work2");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
            //channel.queueDeclare("queue1", false, true, false, null);
            // At the same time, the server will only push one message to the consumer (it does not work for polling)
            //channel.basicQos(1);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;

            finalChannel.basicConsume("queue1", true, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    try{
                        System.out.println("Work2-The message received is:" + new String(delivery.getBody(), "UTF-8"));
                        Thread.sleep(200);
                    }catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println("Work2-Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Test process: start two consumers first, and then start the producer



Summary:
1. work1 and work2 have different message processing capabilities, but the number of messages processed in the end is the same, which is "distributed equally".
2. First allocate and then process, that is, work1 is slow and work2 is fast. Work2 will quickly process its own parts without waiting for work1 to finish processing.

Work mode - Fair Dispatch

Switch type: default
Features: due to the different ability of message receivers to process messages, there is a problem of processing speed and slowness. We need those who can handle faster to process more and those who are slow to process less;
producer:

package work2;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 * @author: Learning companion - flying brother
 * @description: Producer Simple queue producer
 * @Date : 2021/3/2
 */
public class Producer {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("producer");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 6: Prepare to send the contents of the message
            //===============================end topic mode==================================
            for (int i = 1; i <= 20; i++) {
                //Content of the message
                String msg = "Learning companion:" + i;
                // 7: Send a message to the middleware rabbitmq server
                // @params1: switch exchange
                // @params2: queue name / routingkey
                // @params3: property configuration
                // @params4: send message content
                channel.basicPublish("", "queue1", null, msg.getBytes());
            }
            System.out.println("Message sent successfully!");
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Consumer 1

package work2;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Work1 {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("consumer-Work1");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
//            channel.queueDeclare("queue1", false, false, false, null);

            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
            finalChannel.basicQos(1); // At the same time, the server will only push one message to the consumer
            finalChannel.basicConsume("queue1", false, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    try{
                        System.out.println("Work1-The message received is:" + new String(delivery.getBody(), "UTF-8"));
                        Thread.sleep(2000);
                        finalChannel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
                    }catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println("Work1-Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Consumer 2

package work2;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 * @author: Learning companion - flying brother
 * @description: Consumer
 * @Date : 2021/3/2
 */
public class Work2 {
    public static void main(String[] args) {
        // 1: Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: Set connection properties
        connectionFactory.setHost("192.168.229.128");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        Connection connection = null;
        Channel channel = null;
        try {
            // 3: Get connection from connection factory
            connection = connectionFactory.newConnection("consumer-Work2");
            // 4: Get channel from connection
            channel = connection.createChannel();
            // 5: Declare that the queue stores messages
            /*
             *  If the queue does not exist, it is created
             *  Rabbitmq It is not allowed to create two identical queue names, otherwise an error will be reported.
             *
             *  @params1:  queue The name of the queue
             *  @params2:  durable Is the queue persistent
             *  @params3:  exclusive Exclusive, that is, private. If true, the current queue will be locked, other channels cannot be accessed, and the connection will be closed automatically
             *  @params4:  autoDelete Whether to delete the message automatically, and whether to delete the message automatically after the last consumer disconnects.
             *  @params5:  arguments You can set additional parameters of the queue, the validity period of the queue, the maximum length of messages, the message life cycle of the queue, and so on.
             * */
            // Here, if the queue has been created once, it does not need to be defined
            //channel.queueDeclare("queue1", false, true, false, null);
            // 6: Defines a callback that accepts messages
            Channel finalChannel = channel;
            finalChannel.basicQos(1);      // At the same time, the server will only push one message to the consumer
            finalChannel.basicConsume("queue1", false, new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    try{
                        System.out.println("Work2-The message received is:" + new String(delivery.getBody(), "UTF-8"));
                        Thread.sleep(200);
                        finalChannel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
                    }catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
            }, new CancelCallback() {
                @Override
                public void handle(String s) throws IOException {
                }
            });
            System.out.println("Work2-Start receiving messages");
            System.in.read();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Exception in sending message...");
        } finally {
            // 7: Release connection close channel
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

Operation results:


Details of achieving fair distribution:
It can be seen from the results that consumer 2 processes more messages at the same time; The above code implements the fair distribution mode;

  • The consumer receives one message at a time, with the code channel.BasicQos(0, 1, false);
  • Fair distribution requires consumers to turn on manual response and turn off automatic response
  • Turn off the automatic response code channel.BasicConsume("queue_test", false, consumer);
  • The consumer opens the manual response code: channel.BasicAck(ea.DeliveryTag, false);

Summary

(1) When there are many messages in the queue, we usually open multiple consumers to process messages; Fair distribution and polling distribution are both patterns we often use.
(2) The main idea of polling distribution is "equal distribution", regardless of the processing capacity of consumers, all consumers share equally; In this case, the server with weak processing capacity is always processing messages, while the server with strong processing capacity is idle after processing messages;
(3) The main idea of fair distribution is "those who can do more", distribute according to demand, and those with strong ability do more.

Topics: Java RabbitMQ