Introduction to RabbitMQ & Quick Start
1. Getting to know MQ first
1.1. Synchronous and asynchronous communication
There are two ways of communication between microservices: synchronous and asynchronous:
Synchronous communication: Like making a phone call, real-time response is required.
Asynchronous communication: Like sending an email, there is no need to reply immediately.
Both methods have their own advantages and disadvantages. You can get an immediate response when you make a call, but you can't talk to multiple people at the same time. Sending mail can send and receive mail with multiple people at the same time, but there is often a delay in response.
1.1.1. Synchronous communication
The Feign call we learned before is a synchronous method. Although the call can get the result in real time, there are the following problems:
Summarize:
Advantages of synchronous calls:
- Time-sensitive, results can be obtained immediately
Problems with synchronous calls:
- High coupling
- Degraded performance and throughput
- has additional resource consumption
- There is cascading failure problem
1.1.2. Asynchronous communication
Asynchronous calls can avoid the above problems:
Let's take the purchase of goods as an example. After the user pays, he needs to call the order service to complete the order status modification, call the logistics service, allocate the corresponding inventory from the warehouse and prepare for delivery.
In event mode, the payment service is an eventpublisher, after the payment is completed, it is only necessary to publish a successful payment event (event), with the order id in the event.
Order service and logistics service areEvent Subscriber (Consumer), subscribe to the successful payment event, and complete your own business after listening to the event.
In order to remove the coupling between event publishers and subscribers, the two do not communicate directly, but have a middleman (Broker). Publishers publish events to Broker, regardless of who subscribes to events. Subscribers subscribe to events from Broker and don't care who sends the message.
Broker is something like a data bus. All services that need to receive data and send data are sent to this bus. This bus is like a protocol, making communication between services standard and controllable.
benefit:
-
Throughput improvement: there is no need to wait for subscribers to complete processing, and the response is faster
-
Fault isolation: the service is not called directly, and there is no cascading failure problem
-
There is no blocking between calls, which will not cause invalid resource occupation
-
The degree of coupling is extremely low, each service can be flexibly plugged and replaced
-
Traffic peak clipping: No matter how much the traffic of the published event fluctuates, it will be received by Broker, and subscribers can process events at their own speed
shortcoming:
- The structure is complicated, and the business has no obvious process line, which is difficult to manage
- Need to rely on Broker's reliability, security, and performance
Fortunately, the open source software or Broker software on the cloud platform is very mature. The more common one is the MQ technology we are going to learn today.
1.2. Technical comparison:
MQ, Chinese is Message Queue (MessageQueue) , literally it is a queue for storing messages. That is, the Broker in the event-driven architecture.
More common MQ implementations:
- ActiveMQ
- RabbitMQ
- RocketMQ
- Kafka
Comparison of several common MQs:
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
---|---|---|---|---|
Company/Community | Rabbit | Apache | Ali | Apache |
Development language | Erlang | Java | Java | Scala&Java |
protocol support | AMQP,XMPP,SMTP,STOMP | OpenWire,STOMP,REST,XMPP,AMQP | custom protocol | custom protocol |
availability | high | generally | high | high |
Stand-alone throughput | generally | Difference | high | very high |
message delay | microsecond level | Millisecond | Millisecond | within milliseconds |
message reliability | high | generally | high | generally |
Pursuit of availability: Kafka, RocketMQ, RabbitMQ
Pursuit of reliability: RabbitMQ, RocketMQ
Pursuit of throughput: RocketMQ, Kafka
Pursue low message latency: RabbitMQ, Kafka
2. Quick Start
2.1. Install RabbitMQ
To install RabbitMQ, we use Docker to install it in the Centos7 virtual machine.
2.1.1 Download mirror
Method 1: online pull
docker pull rabbitmq:3-management
Method 2: Load from local
The mirror package has been provided in the pre-class materials:
After uploading to the virtual machine, use the command to load the image:
docker load -i mq.tar
2.1.2 Install MQ
Execute the following command to run the MQ container:
docker run \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq \
--hostname mq1 \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:3-management
The basic structure of MQ:
Some roles in RabbitMQ:
- publisher: producer
- consumer: consumer
- exchange: switch, responsible for message routing
- queue: queue, store messages
- virtualHost: virtual host, which isolates the exchange, queue, and message isolation of different tenants
2.2. RabbitMQ message model
RabbitMQ officially provides 5 different Demo examples, corresponding to different message models:
2.3. Import Demo project
The pre-class materials provide a demo project, mq-demo:
After importing, you can see the structure as follows:
Consists of three parts:
- mq-demo: parent project, manage project dependencies
- publisher: the sender of the message
- consumer: the consumer of the message
2.4. Getting Started Case
Model diagram of the simple queue mode:
The official HelloWorld is implemented based on the most basic message queue model, including only three roles:
- publisher: message publisher, send the message to the queue queue
- queue: message queue, responsible for accepting and caching messages
- consumer: Subscribe to the queue and process messages in the queue
2.4.1. publisher implementation
Ideas:
- establish connection
- Create Channels
- declare queue
- Send a message
- Close connections and channels
Code:
package cn.itcast.mq.helloworld;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class PublisherTest {
@Test
public void testSendMessage() throws IOException, TimeoutException {
// 1.建立连接
ConnectionFactory factory = new ConnectionFactory();
// 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
factory.setHost("192.168.150.101");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("itcast");
factory.setPassword("123321");
// 1.2.建立连接
Connection connection = factory.newConnection();
// 2.创建通道Channel
Channel channel = connection.createChannel();
// 3.创建队列
String queueName = "simple.queue";
channel.queueDeclare(queueName, false, false, false, null);
// 4.发送消息
String message = "hello, rabbitmq!";
channel.basicPublish("", queueName, null, message.getBytes());
System.out.println("发送消息成功:【" + message + "】");
// 5.关闭通道和连接
channel.close();
connection.close();
}
}
2.4.2.consumer implementation
Code idea:
- establish connection
- Create Channels
- declare queue
- subscribe news
Code:
package cn.itcast.mq.helloworld;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerTest {
public static void main(String[] args) throws IOException, TimeoutException {
// 1.建立连接
ConnectionFactory factory = new ConnectionFactory();
// 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
factory.setHost("192.168.150.101");
factory.setPort(5672);
factory.setVirtualHost("/");
factory.setUsername("itcast");
factory.setPassword("123321");
// 1.2.建立连接
Connection connection = factory.newConnection();
// 2.创建通道Channel
Channel channel = connection.createChannel();
// 3.创建队列
String queueName = "simple.queue";
channel.queueDeclare(queueName, false, false, false, null);
// 4.订阅消息
channel.basicConsume(queueName, true, new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
// 5.处理消息
String message = new String(body);
System.out.println("接收到消息:【" + message + "】");
}
});
System.out.println("等待接收消息。。。。");
}
}
2.5. Summary
The message sending process of the basic message queue:
-
create connection
-
Create channels
-
Use channel to declare queue
-
Use the channel to send messages to the queue
The message receiving process of the basic message queue:
-
create connection
-
Create channels
-
Use channel to declare queue
-
Define consumer's consumption behavior handleDelivery()
-
Use channels to bind consumers to queues
Study Notes from Dark Horse Programmer
By – Suki 2023/4/8