RabbitMQ working mode with pictures and texts

1, Simple mode

1. Simple mode

The first mock exam is a one to one mode, one producer, one consumer, and the producer sends messages to consumers.

Producer: the program that sends the message

Consumer: the receiver of the message, who will always wait for the message to arrive

Message queue: similar to a mailbox, it can cache messages; The producer delivers the message to it, and the consumer takes the message out of it

2. Example code:

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

        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("118.31.55.110");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        connectionFactory.setVirtualHost("/");

        Connection connecte = connectionFactory.newConnection();
        Channel channel = connecte.createChannel();

        channel.queueDeclare("queue", false, false, false, null);
        String message = "Jaosn Hello World!";

        channel.basicPublish("","queue",null,message.getBytes());

        channel.close();
        connecte.close();

        System.out.println("=====Message sent successfully======");
    }

}


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

        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("118.31.55.110");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        connectionFactory.setVirtualHost("/");

        Connection connecte = connectionFactory.newConnection();
        Channel channel = connecte.createChannel();

        channel.queueDeclare("queue", false, false, false, null);

        //Get data from mq server
        channel.basicConsume("queue",false,new Reciver(channel));

    }
}

class  Reciver extends DefaultConsumer {

    private Channel channel;
    //Rewrite the constructor. The Channel object needs to be passed in from the outer layer and used in handleDelivery
    public Reciver(Channel channel) {
        super(channel);
        this.channel = channel;
    }

    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

        String message = new String(body);
        System.out.println("Message received by consumer:"+message);

        System.out.println("Message TagId: "+envelope.getDeliveryTag());
        //false only confirms to sign in the current message. When set to true, it means to sign in all unsigned messages of the consumer
        channel.basicAck(envelope.getDeliveryTag(), false);
    }
}

2, Work queue mode

1. Work queue mode

In one to many mode, a producer, multiple consumers and a queue, each consumer obtains a unique message from the queue. Compared with the simple mode of the entry program, there are one or more consumers, and multiple consumers consume messages in the same queue together.

  • If there are multiple consumers in a queue, the relationship between consumers for the same message is a competitive relationship
  • Work mode for the case of heavy tasks or more tasks, using work queue can improve the speed of task processing. For example, if multiple SMS services are deployed, only one node needs to be sent successfully.

2. Code:

//Order system
public class OrderSystem {

    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        for(int i = 1 ; i <= 100 ; i++) {
            SMS sms = new SMS("passenger" + i, "13900000" + i, "Your ticket has been booked successfully");
            String jsonSMS = new Gson().toJson(sms);
            channel.basicPublish("" , RabbitConstant.QUEUE_SMS , null , jsonSMS.getBytes());
        }
        System.out.println("Sending data succeeded");
        channel.close();
        connection.close();
    }
}
//SMS service 1
public class SMSSender1 {

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


        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        //If basicQos (1) is not written, MQ automatically sends all requests to all consumers on average
        //basicQos,MQ no longer sends multiple requests to consumers at one time, but after the consumer processes a message (after confirmation), it obtains a new request from the queue
        channel.basicQos(1);//Take one after processing

        channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String jsonSMS = new String(body);
                System.out.println("SMSSender1-SMS sent successfully:" + jsonSMS);

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }


}

//SMS service 2
public class SMSSender2 {

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


        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        //If basicQos (1) is not written, MQ automatically sends all requests to all consumers on average
        //basicQos,MQ no longer sends multiple requests to consumers at one time, but after the consumer processes a message (after confirmation), it obtains a new request from the queue
        channel.basicQos(1);//Take one after processing

        channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String jsonSMS = new String(body);
                System.out.println("SMSSender2-SMS sent successfully:" + jsonSMS);

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }
}


//SMS service 3
public class SMSSender3 {


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


        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();

        channel.queueDeclare(RabbitConstant.QUEUE_SMS, false, false, false, null);

        //If basicQos (1) is not written, MQ automatically sends all requests to all consumers on average
        //basicQos,MQ no longer sends multiple requests to consumers at one time, but after the consumer processes a message (after confirmation), it obtains a new request from the queue
        channel.basicQos(1);//Take one after processing

        channel.basicConsume(RabbitConstant.QUEUE_SMS , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String jsonSMS = new String(body);
                System.out.println("SMSSender3-SMS sent successfully:" + jsonSMS);

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }
}

3, Publish subscribe mode

1. Schematic diagram:

2. Publish subscribe mode

In the subscription model, an Exchange role is added, and the process changes slightly:

The producer, that is, the program that sends the message, but it is no longer sent to the queue, but to X (switch)

The consumer, the receiver of the message, will always wait for the message to arrive

Message queue, receiving messages and caching messages

On the one hand, the switch receives messages sent by producers. On the other hand, you know how to process messages, such as delivering to a special queue, delivering to all queues, or discarding messages. How to operate depends on the type of Exchange. There are three common types of Exchange:

  • Fanout: broadcast and deliver messages to all queues bound to the switch
  • Direct: direct, which sends messages to queues that match the specified routing key
  • Topic: wildcard, which gives the message to the queue conforming to the routing pattern

Switch: it is only responsible for forwarding messages and does not have the ability to store messages. Therefore, if there is no queue bound to Exchange or no queue that meets the routing rules, the messages will be lost!

3. Example:

(1) Figure

(2) Create queue

(3) Create switch

(4) The queue is bound to the switch

(5) Code:

//Publisher
public class WeatherBureau {


    public static void main(String[] args) throws Exception {
        Connection connection = RabbitUtils.getConnection();
        String input = new Scanner(System.in).next();
        Channel channel = connection.createChannel();

        //The first parameter is the switch name, and other parameters are the same as before
        channel.basicPublish(RabbitConstant.EXCHANGE_WEATHER,"" , null , input.getBytes());

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


//subscriber
public class Sina {

    public static void main(String[] args) throws IOException {
        //Get TCP long connection
        Connection connection = RabbitUtils.getConnection();
        //Get virtual connection
        final Channel channel = connection.createChannel();
        //Declare queue information
        channel.queueDeclare(RabbitConstant.QUEUE_SINA, false, false, false, null);

        //queueBind is used to bind queues to switches
        //Parameter 1: queue name parameter 2: interactive machine name parameter 3: routing key (temporarily unavailable)
        channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER, "");
        channel.basicQos(1);
        channel.basicConsume(RabbitConstant.QUEUE_SINA , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("Weather information received by Sina weather:" + new String(body));
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }

}



public class BiaDu {

    public static void main(String[] args) throws IOException {
        //Get TCP long connection
        Connection connection = RabbitUtils.getConnection();
        //Get virtual connection
        final Channel channel = connection.createChannel();
        //Declare queue information
        channel.queueDeclare(RabbitConstant.QUEUE_BAIDU, false, false, false, null);

        //queueBind is used to bind queues to switches
        //Parameter 1: queue name parameter 2: interactive machine name parameter 3: routing key (temporarily unavailable)
        channel.queueBind(RabbitConstant.QUEUE_BAIDU, RabbitConstant.EXCHANGE_WEATHER, "");
        channel.basicQos(1);
        channel.basicConsume(RabbitConstant.QUEUE_BAIDU , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("Weather information received by Baidu weather:" + new String(body));
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }

(6) Summary:

a. The switch needs to bind to the queue. After binding, a message can be received by multiple consumers.

b. Differences between publish subscribe mode and work queue mode:

  • Work queue mode does not need to define switches, while publish / subscribe mode needs to define switches
  • The producer of publish / subscribe mode sends messages to the switch, and the producer of work queue mode sends messages to the queue (the default switch is used at the bottom)
  • The publish / subscribe mode needs to set the binding between the queue and the switch. The work queue mode does not need to be set. In fact, the work queue mode will bind the queue to the default switch

4, Routing mode

1. Routing mode:

  • The binding between the queue and the switch cannot be arbitrary, but a routing key should be specified
  • When sending a message to Exchange, the sender of the message must also specify the RoutingKey of the message
  • Exchange will no longer deliver messages to each bound queue, but will judge according to the routing key of the message. Messages will be received only if the routing key of the queue is completely consistent with the routing key of the message

2. Figure:

Illustration:

  • Producer: sends a message to the switch. When sending a message, a routing key will be specified
  • Switch: receive the producer's message, and then submit the message to the queue that exactly matches the routing key
  • Consumer 1: its queue specifies the messages whose routing key needs to be info and error
  • Consumer 2: its queue specifies the messages whose routing key needs to be error and warning

3. Example diagram:

4. Code:

//Publisher
public class WeatherBureau {

    public static void main(String[] args) throws Exception {

        Map area = new LinkedHashMap<String, String>();
        area.put("china.hunan.changsha.20201127", "Weather data of Changsha, Hunan, China 20201127");
        area.put("china.hubei.wuhan.20201127", "Weather data of Wuhan, Hubei, China 20201127");
        area.put("china.hunan.zhuzhou.20201127", "Weather data of Zhuzhou, Hunan, China 20201128");
        area.put("us.cal.lsj.20201127", "Weather data of Los Angeles, California 20201127");

        area.put("china.hebei.shijiazhuang.20201128", "China Hebei Shijiazhuang 20201128 weather data");
        area.put("china.hubei.wuhan.20201128", "Weather data of Wuhan, Hubei, China 20201128");
        area.put("china.henan.zhengzhou.20201128", "Weather data of Zhengzhou, Henan, China 20201128");
        area.put("us.cal.lsj.20201128", "Weather data of Los Angeles, California 20201128");


        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();

        Iterator<Map.Entry<String, String>> itr = area.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry<String, String> me = itr.next();
            //The first parameter is the switch name, and the second parameter is the routing key of the message
            channel.basicPublish(RabbitConstant.EXCHANGE_WEATHER_ROUTING,me.getKey() , null , me.getValue().getBytes());
        }

        channel.close();
        connection.close();
    }
}
//consumer
public class Sina {
    public static void main(String[] args) throws IOException {
        //Get TCP long connection
        Connection connection = RabbitUtils.getConnection();
        //Get virtual connection
        final Channel channel = connection.createChannel();
        //Declare queue information
        channel.queueDeclare(RabbitConstant.QUEUE_SINA, false, false, false, null);

        //Specify the relationship between the queue and the switch and the routing key
        channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER_ROUTING, "us.cal.lsj.20201127");
        channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER_ROUTING, "china.hubei.wuhan.20201127");
        channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER_ROUTING, "us.cal.lsj.20201128");
        channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER_ROUTING, "china.henan.zhengzhou.20201012");

        channel.basicQos(1);
        channel.basicConsume(RabbitConstant.QUEUE_SINA , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("Weather information received by Sina weather:" + new String(body));
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }
}


public class BiaDu {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(RabbitConstant.QUEUE_BAIDU, false, false, false, null);
        //queueBind is used to bind queues to switches
        //Parameter 1: queue name parameter 2: interactive machine name parameter 3: routing key
        channel.queueBind(RabbitConstant.QUEUE_BAIDU, RabbitConstant.EXCHANGE_WEATHER_ROUTING, "china.hunan.changsha.20201127");
        channel.queueBind(RabbitConstant.QUEUE_BAIDU, RabbitConstant.EXCHANGE_WEATHER_ROUTING, "china.hebei.shijiazhuang.20201128");
        channel.basicQos(1);
        channel.basicConsume(RabbitConstant.QUEUE_BAIDU , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("Weather information received by Baidu weather:" + new String(body));
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }
}

5. Summary

The Routing mode requires the queue to specify the routing key when binding the switch, and the message will be forwarded to the queue matching the routing key.

5, Wildcard pattern

1. Wildcard pattern

  • Compared with Direct, Topic can route messages to different queues according to RoutingKey. However, Topic Exchange allows the queue to use wildcards when Binding routing keys!
  • Routingkey s are generally composed of one or more words, which are separated by ".", such as item.insert
  • Wildcard rule: # match one or more words, * match exactly one word, for example: item. # can match item.insert.abc or item.insert, and item. * can only match item.insert

2. Example code:

//Publisher
public class WeatherBureau {


    public static void main(String[] args) throws Exception {

        Map area = new LinkedHashMap<String, String>();
        area.put("china.hunan.changsha.20201127", "Weather data of Changsha, Hunan, China 20201127");
        area.put("china.hubei.wuhan.20201127", "Weather data of Wuhan, Hubei, China 20201127");
        area.put("china.hunan.zhuzhou.20201127", "Weather data of Zhuzhou, Hunan, China 20201127");
        area.put("us.cal.lsj.20201127", "Weather data of Los Angeles, California 20201127");

        area.put("china.hebei.shijiazhuang.20201128", "China Hebei Shijiazhuang 20201128 weather data");
        area.put("china.hubei.wuhan.20201128", "Weather data of Wuhan, Hubei, China 20201128");
        area.put("china.henan.zhengzhou.20201128", "Weather data of Zhengzhou, Henan, China 20201128");
        area.put("us.cal.lsj.20201128", "Weather data of Los Angeles, California 20201128");


        Connection connection = RabbitUtils.getConnection();
        Channel channel = connection.createChannel();

        Iterator<Map.Entry<String, String>> itr = area.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry<String, String> me = itr.next();
            //The first parameter is the switch name, and the second parameter is the routing key of the message
            channel.basicPublish(RabbitConstant.EXCHANGE_WEATHER_TOPIC,me.getKey() , null , me.getValue().getBytes());

        }

        channel.close();
        connection.close();
    }
}
//consumer
public class Sina {

    public static void main(String[] args) throws IOException {
        //Get TCP long connection
        Connection connection = RabbitUtils.getConnection();
        //Get virtual connection
        final Channel channel = connection.createChannel();
        //Declare queue information
        channel.queueDeclare(RabbitConstant.QUEUE_SINA, false, false, false, null);

        //Specify the relationship between the queue and the switch and the routing key
        channel.queueBind(RabbitConstant.QUEUE_SINA, RabbitConstant.EXCHANGE_WEATHER_TOPIC, "us.#");

        channel.basicQos(1);
        channel.basicConsume(RabbitConstant.QUEUE_SINA , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("Weather information received by Sina weather:" + new String(body));
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });
    }

}


public class BiaDu {

    public static void main(String[] args) throws IOException {
        Connection connection = RabbitUtils.getConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(RabbitConstant.QUEUE_BAIDU, false, false, false, null);
        //queueBind is used to bind queues to switches
        //Parameter 1: queue name parameter 2: interactive machine name parameter 3: routing key
        channel.queueBind(RabbitConstant.QUEUE_BAIDU, RabbitConstant.EXCHANGE_WEATHER_TOPIC, "*.*.*.20201127");
        channel.basicQos(1);
        channel.basicConsume(RabbitConstant.QUEUE_BAIDU , false , new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("Weather information received by Baidu weather:" + new String(body));
                channel.basicAck(envelope.getDeliveryTag() , false);
            }
        });

    }

}

Tags: RabbitMQ MQ

Posted on Wed, 15 Sep 2021 15:48:46 -0400 by khaine