消息队列(MQ)
一、简介
消息队列(Message Queue,简称MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。
二、选择合适的MQ
目前市面上有很多成熟的MQ产品,如RabbitMQ、Kafka、ActiveMQ等。选择时需要考虑以下因素:
- 性能:根据业务场景评估吞吐量和延迟要求。
- 可靠性:确保消息不丢失,特别是在网络故障或系统崩溃的情况下。
- 易用性:包括API的友好程度、社区支持和文档完善度。
- 扩展性:是否支持集群部署,能否方便地水平扩展。
三、基本概念
- 生产者(Producer)
- 负责创建并发送消息到消息队列中。例如,在Java中可以使用
ConnectionFactory
创建连接,然后通过Session
创建消息生产者对象。
- 负责创建并发送消息到消息队列中。例如,在Java中可以使用
- 消费者(Consumer)
- 从消息队列接收消息并处理。可以通过监听的方式获取消息,如在Java中使用
MessageListener
接口实现消息监听逻辑。
- 从消息队列接收消息并处理。可以通过监听的方式获取消息,如在Java中使用
- 消息(Message)
- 包含要传输的数据内容,可以是文本、二进制数据等。需要定义好消息格式,以便生产者和消费者能够正确解析。
四、简单示例(以RabbitMQ为例)
(一)引入依赖(Maven项目)
xml
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.16.0</version>
</dependency>
(二)生产者代码
java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] args) throws Exception {
// 创建连接工厂
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 + "'");
}
}
}
(三)消费者代码
java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
public class Consumer {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] args) 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");
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 -> { });
}
}
五、注意事项
- 消息确认机制
- 确保消息被成功消费后才从队列中移除。对于重要的业务场景,开启消息确认功能,防止消息丢失。
- 死信队列
- 当消息无法被正常消费时(如多次重试失败),可以将消息路由到死信队列,便于后续排查问题。
- 高可用配置
- 在生产环境中,为了保证系统的稳定性和可靠性,应该搭建MQ集群,并且合理设置主备切换策略等。