Article Directory
Official document address: 1 "Hello World!"
The simplest thing.
Prerequisites
This tutorial assumes that you have installed RabbitMQ and is running on the local host port (5672).
Introduction
RabbitMQ is a message broker responsible for receiving and forwarding messages. You can think of it as a post office: when you put the mail you want to post into a mailbox, you can be sure that the postman will eventually deliver the mail to the recipient you specify. In this analogy, RabbitMQ is a mailbox, a post office and a postman.
The main difference between RabbitMQ and the post office is that it does not deal with paper, but a binary large object that accepts, stores, and forwards data messages.
RabbitMQ and general messaging use some terminology.
- Production is nothing more than delivery. The procedure for sending a message is
producer
:
queue
Is the name of the mailbox that resides in RabbitMQ. A queue is only limited by the host's memory and disk, and it is essentially a large message buffer. Many producers can send messages to a queue, and many consumers can try to receive data from a queue. We represent the queue like this:
- Consumption and reception have similar meanings.
consumer
Is a program waiting to receive a message:
Hello World
In this part of the tutorial, we will Java
write two programs: a producer who sends a message and a consumer who receives the message and prints it out. We will use message queue delivery "Hello World"
as an example to explain.
In the chart below, it "P"
is our producer and "C"
our consumer. The box in the middle is a queue.
The Java client library
RabbitMQ uses multiple protocols. This tutorial usesAMQP 0-9-1
, which is an open and universal messaging protocol. RabbitMQ has clients in many different languages. We will use the Java client provided by RabbitMQ.
Download the client library and its dependencies ( SLF4J API and SLF4J Simple ). Copy these files and the Java files in the tutorial to your working directory.
Please note that for the tutorial, itSLF4J Simple
is enough, but you should use a complete log library in a production environment, for exampleLogback
.
(There is also a RabbitMQ Java client in the central Maven repository, with groupId forcom.rabbitmq
and artifactId foramqp-client
).
Now that we have the Java client and its dependencies, we can write some code.
Here is a supplement to the Maven dependency of RabbitMQ's Java client to facilitate the use of Maven projects:
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.1</version>
</dependency>
Producer
We will call the message publisher (sender) Send
and message consumer (receiver) Recv
. The publisher will connect to RabbitMQ, send a message, and then exit.
In Send.java
, we need to import some classes:
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
Create a class and name the queue:
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
...
}
}
Then we can create a connection to the server:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
}
Here we connect to the RabbitMQ node on the local machine-that is localhost
. If we want to connect to a node on another machine, we only need to specify its hostname or IP
address here.
Next we create one channel
, which is where most of the APIs to accomplish the task are located. Note that we can use try-with-resources
statements, because Connection
and Channel
are all realized java.io.Closeable
. This way we don't need to explicitly turn them off in the code.
To send a message, you must first declare a queue; then publish a message to the queue, all of which are try-with-resources
implemented in the statement:
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
Declare that the queue is idempotent-it will only be created if the queue does not exist. The content of the message is a byte array, so you can encode anything in it.
This is the complete Send.java
code:
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wangbo
* @date 2019/10/22 18:05
*/
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
//创建一个连接器连接到服务器
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try(Connection connection = factory.newConnection()){
//创建一个通道
Channel channel = connection.createChannel();
//声明一个队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
//发布一条消息
channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + message + "'");
}
}
}
The producer does not work.
If this is the first time you use RabbitMQ, the code is executed but you do not see the "sent" message, the reason may be that the service does not have enough free disk space when it starts (by default, it needs at least200MB
free space) ), therefore refuse to receive messages. Check the server log file to confirm the problem and reduce the limit if necessary. The configuration file document will show you how to set it updisk_free_limit
.
consumer
Our consumer listens to messages from RabbitMQ, so unlike the publisher who can quit by publishing a message, we need to keep the consumer running to listen to the message and print it out.
Recv.java
The classes that need to be imported are Send.java
roughly the same:
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
We will use the DeliverCallback
interface to buffer the messages pushed to us by the server.
The setup is basically the same as the producer server; we open a connection and a channel, and declare the queue we will use. Note that it needs to match the queue name published by the producer.
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
}
}
Note that we also declare the queue here. Because the consumer may start before the producer starts, so here is to ensure that the queue exists when using the messages in the queue.
Why not use try-with-resource
statements to automatically close channels and connections? Because we want the producer to listen to the message asynchronously, when the message arrives, the process remains active.
We will tell the server to send us the messages in the queue. Because it will push messages asynchronously, we provide a callback in the form of an object that will buffer the messages until we are ready to use them. This is DeliverCallback
the role of subclasses.
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
This is the complete Recv.java
code:
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* @author wangbo
* @date 2019/10/22 18:25
*/
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
//创建一个连接器连接到服务器
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
//创建一个通道
Channel channel = connection.createChannel();
//声明一个队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
//回调对象
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
Put them together
You can use RabbitMQ's Java client to compile these two in the classpath:
javac -cp amqp-client-5.7.1.jar Send.java Recv.java
To run them, you need to add rabbitmq-client.jar
their dependencies on the classpath . In the terminal, run the consumer (receiver):
java -cp .:amqp-client-5.7.1.jar:slf4j-api-1.7.26.jar:slf4j-simple-1.7.26.jar Recv
Then, run the producer (sender):
java -cp .:amqp-client-5.7.1.jar:slf4j-api-1.7.26.jar:slf4j-simple-1.7.26.jar Send
On Windows, use semicolons instead of colons to separate items in the classpath.
The consumer will print the message it gets from the producer via RabbitMQ. The consumer will continue to run, waiting for the message (you can use it Ctrl+C
to stop it), so you need to run the producer from another terminal.
Queue list
You may want to see which queues RabbitMQ has and how many messages are in the queue. You can use therabbitmqctl
tool (with administrator rights) :
sudo rabbitmqctl list_queues
On Windows:
rabbitmqctl.bat list_queues
Next is the first 2
part, building a simple work queue.
Tip
To save typing, you can set an environment variable for the classpath.
export CP=.:amqp-client-5.7.1.jar:slf4j-api-1.7.26.jar:slf4j-simple-1.7.26.jar
java -cp $CP Send
On Windows:
set CP=.;amqp-client-5.7.1.jar;slf4j-api-1.7.26.jar;slf4j-simple-1.7.26.jar
java -cp %CP% Send
practical testing
The following is not the content of the official tutorial, but my test of the official tutorial on the local Windows system.
Download three Jar packages and put them in the directory D:\test
. Put the Send.java
sum in Recv.java
this directory. Execute the compilation command:
D:\test>javac -cp amqp-client-5.7.1.jar Send.java Recv.java
Start the consumer and run Recv.class
:
D:\test>java -cp .;amqp-client-5.7.1.jar;slf4j-api-1.7.26.jar;slf4j-simple-1.7.26.jar Recv
[*] Waiting for messages. To exit press CTRL+C
To start the producer in a new window, run Send.class
:
D:\test>java -cp .;amqp-client-5.7.1.jar;slf4j-api-1.7.26.jar;slf4j-simple-1.7.26.jar Send
[x] Sent 'Hello World!'
At this time, the Hello World!
string sent by the producer can be received in the consumer window .
[x] Received 'Hello World!'
After testing, set the environment variables to simplify the message sending command, as shown below, there is no problem:
D:\test>set CP=.;amqp-client-5.7.1.jar;slf4j-api-1.7.26.jar;slf4j-simple-1.7.26.jar
D:\test>java -cp %CP% Send
[x] Sent 'Hello World!'
D:\test>java -cp %CP% Send
[x] Sent 'Hello World!'
D:\test>
Next, test the rabbitmqctl
tool to see what queues RabbitMQ has and how many messages are in the queue.
D:\Programmer\RabbitMQ Server\rabbitmq_server-3.7.8\sbin>rabbitmqctl.bat list_queues
Timeout: 60.0 seconds ...
Listing queues for vhost / ...
hello 0
You can see that there is a queue, the name is hello
, the message 0
bar.