Seven modes introduction and application scenarios
Simple mode (Hello World)
Do the simplest thing, a producer corresponds to a consumer, RabbitMQ is equivalent to a message broker, responsible for forwarding A’s message to B
application scenario : put the sent emails in the message queue, and then the mail service gets the emails in the queue and sends them to the recipients
Work queue mode (Work queues)
Distribute tasks among multiple consumers (competitive consumer mode). One producer corresponds to multiple consumers. It is generally suitable for performing resource-intensive tasks. A single consumer cannot handle it, and multiple consumers are required to process it.
application scenario : It takes 10s to process an order, and multiple orders can be placed in the message queue at the same time, and then multiple consumers can be processed at the same time. This is parallel, not the serial situation of a single consumer
Subscription mode (Publish/Subscribe)
When you send a message to many consumers at once, the message sent by one producer will be acquired by multiple consumers, that is, the message will be broadcast to all consumers.
application scenario : After updating the product inventory, multiple caches and multiple databases need to be notified. The structure here should be:
- A fanout type switch fan out two message queues, namely the cache message queue and the database message queue
- A cache message queue corresponds to multiple cache consumers
- A database message queue corresponds to multiple database consumers
Routing mode (Routing)
Selectively (Routing key) receive messages, send messages to the exchange and specify the routing key. Consumers need to specify the routing key when binding the queue to the exchange, and only consume messages with the specified routing key
application scenario : If an iphone12 is added to the product inventory, and the iphone12 promotion consumer specifies the routing key as iphone12, only this promotion will receive the message, and other promotions will not care about or consume the message of this routing key.
Topics
Receive messages according to the topic (Topics), and match the routing key with a certain pattern. At this time, the queue needs to be bound to a pattern, #matches one or more words, * matches only one word.
Application Scenario : Same as above, iphone promotion can receive messages with the theme of iphone, such as iphone12, iphone13, etc.
Remote procedure call (RPC)
If we need to run a function on a remote computer and wait for the result, we can use RPC. The specific process can be seen in the figure. application scenario : need to wait for the interface to return data, such as order payment
Publisher Confirms
Reliable release confirmation is carried out with the publisher, and the publisher confirms that it is an extension of RabbitMQ, which can achieve reliable release. After enabling publisher confirmation on the channel, RabbitMQ will asynchronously acknowledge the messages published by the sender, which means that they have been processed on the server side. (Search for the technical road of migrant workers in the official account, see more Java back-end technology stacks and selected interview questions)
application scenario : higher requirements for message reliability, such as wallet deductions
Code demo
There is no demonstration of the latter two modes in the code. If you are interested, you can study by yourself
Simple mode
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Sender {
private final static String QUEUE_NAME = "simple_queue";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 声明队列
// queue:队列名
// durable:是否持久化
// exclusive:是否排外 即只允许该channel访问该队列 一般等于true的话用于一个队列只能有一个消费者来消费的场景
// autoDelete:是否自动删除 消费完删除
// arguments:其他属性
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//消息内容
String message = "simplest mode message";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println("[x]Sent '" + message + "'");
//最后关闭通关和连接
channel.close();
connection.close();
}
}
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;
public class Receiver {
private final static String QUEUE_NAME = "simplest_queue";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
// 获取连接
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
Work queue mode
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;
public class Receiver1 {
private final static String QUEUE_NAME = "queue_work";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 同一时刻服务器只会发送一条消息给消费者
channel.basicQos(1);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
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;
public class Receiver2 {
private final static String QUEUE_NAME = "queue_work";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 同一时刻服务器只会发送一条消息给消费者
channel.basicQos(1);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Sender {
private final static String QUEUE_NAME = "queue_work";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 声明队列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i = 0; i < 100; i++) {
String message = "work mode message" + i;
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println("[x] Sent '" + message + "'");
Thread.sleep(i * 10);
}
channel.close();
connection.close();
}
}
Publish and subscribe model
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
public class Receive1 {
private static final String EXCHANGE_NAME = "logs";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "");
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(queueName, true, deliverCallback, consumerTag -> {
});
}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
public class Receive2 {
private static final String EXCHANGE_NAME = "logs";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "");
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] Received2 '" + message + "'");
};
// 消费者,有消息时出发订阅回调函数
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {
});
}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Sender {
private static final String EXCHANGE_NAME = "logs";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String message = "publish subscribe message";
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + message + "'");
channel.close();
connection.close();
}
}
Routing mode
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;
public class Receiver1 {
private final static String QUEUE_NAME = "queue_routing";
private final static String EXCHANGE_NAME = "exchange_direct";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 指定路由的key,接收key和key2
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key");
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key2");
channel.basicQos(1);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
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;
public class Receiver2 {
private final static String QUEUE_NAME = "queue_routing2";
private final static String EXCHANGE_NAME = "exchange_direct";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 仅接收key2
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key2");
channel.basicQos(1);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Sender {
private final static String EXCHANGE_NAME = "exchange_direct";
private final static String EXCHANGE_TYPE = "direct";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 交换机声明
channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE);
// 只有routingKey相同的才会消费
String message = "routing mode message";
channel.basicPublish(EXCHANGE_NAME, "key2", null, message.getBytes());
System.out.println("[x] Sent '" + message + "'");
// channel.basicPublish(EXCHANGE_NAME, "key", null, message.getBytes());
// System.out.println("[x] Sent '" + message + "'");
channel.close();
connection.close();
}
}
Theme mode
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;
public class Receiver1 {
private final static String QUEUE_NAME = "queue_topic";
private final static String EXCHANGE_NAME = "exchange_topic";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 可以接收key.1
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key.*");
channel.basicQos(1);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
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;
public class Receiver2 {
private final static String QUEUE_NAME = "queue_topic2";
private final static String EXCHANGE_NAME = "exchange_topic";
private final static String EXCHANGE_TYPE = "topic";
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// *号代表单个单词,可以接收key.1
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "*.*");
// #号代表多个单词,可以接收key.1.2
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "*.#");
channel.basicQos(1);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" +
delivery.getEnvelope().getRoutingKey() + "':'" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
});
}
}
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Sender {
private final static String EXCHANGE_NAME = "exchange_topic";
private final static String EXCHANGE_TYPE = "topic";
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE);
String message = "topics model message with key.1";
channel.basicPublish(EXCHANGE_NAME, "key.1", null, message.getBytes());
System.out.println("[x] Sent '" + message + "'");
String message2 = "topics model message with key.1.2";
channel.basicPublish(EXCHANGE_NAME, "key.1.2", null, message2.getBytes());
System.out.println("[x] Sent '" + message2 + "'");
channel.close();
connection.close();
}
}
Introduction to four types of switches
- Direct exchange: A switch with routing function. When binding to this switch, you need to specify a routing_key. When the switch sends a message, routing_key is required, and the message will be sent to the corresponding queue
- Fanout exchange: Broadcast messages to all queues without any processing, the fastest
- Topic exchange: Add pattern matching on the basis of directly connected switches, that is, pattern matching on routing_key, * stands for one word, # stands for multiple words
- Headers exchange: Ignore routing_key and use Headers information (a Hash data structure) for matching. The advantage is that there are more and more flexible matching rules.
to sum up
There are application scenarios in so many queue modes, you can choose according to the application scenario examples
Author: I think I know I am
blog.csdn.net/qq_32828253/article/details/110450249
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。