RabbitMQ producer consumer model

Posted by phpbeginer on Mon, 24 Jan 2022 13:16:16 +0100

As the mainstream MQ message queue middleware, RabbitMQ also has a producer consumer model, that is to say

After the producer sends the message, the consumer receives the specific message. This article mainly provides a detailed overview of RabbitMQ producers

Delivery and consumer monitoring.

1, Messaging process

The following is a detailed summary of the overall process of RabbitMQ message queue server, which is summarized as follows:

  • The producer is only responsible for delivering messages to Exchange. This process does not need to pay attention to the Queue
  • Exchange delivers the message to the Queue
  • As a consumer program, it is responsible for listening to the messages of the Queue
  • In order to ensure the accuracy and timeliness of message delivery, there will be a certain binding relationship between Exchange and Queue, that is, routing Key

2, MQ delivery

According to the architecture model of RabbitMQ, in the producer model and consumer model, producers and consumers do not know

The existence of the other party is the characteristic of asynchronous communication. As a producer, it only needs to deliver messages to Exchange in this process

Producers in do not need to pay attention to the Queue. In fact, producers can't pay attention to the Queue. How does the message make consumers pay attention to the Queue

To listen and receive? This means that a mapping relationship will be established between Exchange and Queue, which is not

What producers need to pay attention to. As a consumer, you don't need to pay attention to Exchange, but just listen to the Queue.

2.1. Introducing RabbitMQ jar

The premise of using RabbitMQ is to introduce the jar of RabbitMQ, so it needs to be in POM RabbitMQ is added to the XML file

The server and client are as follows:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>

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

2.2 delivery steps of producers

If the producer needs to deliver the message to Exchange, its steps are summarized as follows:

ConnectionFactory Class is responsible for obtaining the connection factory

Connection Class to get a connection

Channel Create a data channel that can send and receive messages

The following is the complete code delivered by the producer, as follows:

package com.example.rabbitmq.quickstart;

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

public class Producer
{
    public static void main(String[] args) throws  Exception {
        //Create connection factory
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //Configure the address information of the connection mq
        connectionFactory.setHost("101.**.***.84");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("wuya");
        connectionFactory.setPassword("java");
        connectionFactory.setVirtualHost("/");

        //Connection factory create connection
        Connection connection = connectionFactory.newConnection();

        //Create a Channel through connection
        Channel channel = connection.createChannel();

        //Send specific data information through channel
        String msg = "Hello RabbitMQ";
        channel.basicPublish("saas", "", null, msg.getBytes());
        //After sending the message successfully, close the specific connection
        channel.close();
        connection.close();
    }
}

From the above, we can see that we first need to connect to the RabbitMQ server, and then we need to send a message

Specify a specific Exchange, because for the producer, it only focuses on delivering messages to Exchange.

2.3 consumer monitoring

Producers deliver messages to Exchange, so consumers need to listen to specific messages. The whole process of monitoring is also

RabbitMQ server needs to be established. The codes involved in this part are as follows:

package com.example.rabbitmq.quickstart;

import com.rabbitmq.client.*;

public class Consumer
{
    //Define exchange
    private static final String EXCHANGE = "saas";
    //Define queue
    private  static  final String queueName="saas";

    public static void main(String[] args) throws  Exception
    {
        try{
            //Create connection factory
            ConnectionFactory connectionFactory=new ConnectionFactory();
            //Configure the address information of the connection mq
            connectionFactory.setHost("101.**.***.84");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("wuya");
            connectionFactory.setPassword("java");
            connectionFactory.setVirtualHost("/");

            //Connection factory create connection
            Connection connection=connectionFactory.newConnection();

            //Create a Channel through connection
            Channel channel=connection.createChannel();

            //Set the exchange type to fanout
            channel.exchangeDeclare(EXCHANGE,BuiltinExchangeType.FANOUT);

        /*
         Define a queue
         * After a queue receives data, the consumer can receive specific data from the queue
         * param1:Queue name
         * param2:Persistent
         * param3:Does the queue have exclusive access to this connection
         * param4:Delete this queue automatically when it is no longer in use
         * param5:Queue parameters
         * */
            channel.queueDeclare(queueName,true,false,false,null);

            channel.queueBind(queueName,EXCHANGE,"");

            //Create a consumer to consume data
            DefaultConsumer consumer=new DefaultConsumer(channel)
            {
                @Override
                public void handleDelivery(
                        String consumerTag,
                        com.rabbitmq.client.Envelope envelope,
                        AMQP.BasicProperties properties,
                        byte [] body) throws  java.io.IOException
                {
                    String message=new String(body);
                    System.out.println("The message received is:"+message);
                };
            };
            // Listen to the queue and get data from the queue
            System.out.println("The consumer program started successfully and is ready to receive the producer's data:\n");
            channel.basicConsume(queueName,consumer);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

In the above, we can see that the name of Exchange is the same as that of the production side. Only in this way can the binding relationship be established,

To put it more simply, the producer sends messages to Exchange, and then there is a layer mapping relationship between Exchange and Queue,

Only in this way can the consumer listen to the queue and receive the message.

2.4 binding relationship

Just now, we talked about the binding relationship between Exchange and Queue. Here is a specific demonstration for this part. Let's start consumers first

After the program is started successfully, it will automatically create Exchange and Queue, and you can bind from Exchange and Queue

The corresponding binding relationship can be obtained in.

2.4.1. Exchange binding relationship

The following figure shows the Exchange created after the consumer's program is started and its binding relationship, as follows:

2.4.2 consumer binding relationship

In the binding relationship of Exchange, click saas in To to automatically jump To Queue, as shown below:

2.5.406 error avoidance

When learning RabbitMQ, many beginners always create Exchange and Queue in advance. As a result, consumers have a lot of applications

The specific errors are as follows:

java.io.IOException
	at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:129)
	at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:125)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:147)
	at com.rabbitmq.client.impl.ChannelN.exchangeDeclare(ChannelN.java:783)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:252)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:242)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:222)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:227)
	at com.example.rabbitmq.quickstart.Consumer.main(Consumer.java:31)
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'saas' in vhost '/': received 'fanout' but current is 'direct', class-id=40, method-id=10)
	at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
	at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
	at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:502)
	at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:293)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:141)
	... 6 more
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'saas' in vhost '/': received 'fanout' but current is 'direct', class-id=40, method-id=10)
	at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:517)
	at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:341)
	at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:182)
	at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:114)
	at com.rabbitmq.client.impl.AMQConnection.readFrame(AMQConnection.java:739)
	at com.rabbitmq.client.impl.AMQConnection.access$300(AMQConnection.java:47)
	at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:666)
	at java.lang.Thread.run(Thread.java:748)

In fact, the easiest way to solve this problem is to delete the Exchange and Queue created by yourself. After deletion, execute the consumer's request again

Program, it will automatically create Exchange and Queue, and will not report a series of specific problems. After solving the above problems, try again

By executing the producer's program, you can see that the message sent by the producer can be monitored by the consumer. Thank you for reading. The next article is mainly about

Introduce Exchange details.