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.