ActiveMQ 是一个开源的消息中间件,实现了 JMS(Java Message Service)1.1 规范。ActiveMQ 的 Queue 模式是一种点对点的消息传递模式,具有以下功能和特点:
功能
- 消息存储与转发:生产者将消息发送到队列中,消费者从队列中取出并消费消息。
- 支持多个消费者:虽然一个消息只能被一个消费者消费,但队列可以有多个消费者,消息会按照某种策略分配给不同的消费者。
- 消息持久化:默认情况下,消息是持久化的,即使 ActiveMQ 服务器重启,消息也不会丢失。
- 消息优先级:支持设置消息的优先级,高优先级的消息会优先被消费。
特点
- 解耦:生产者和消费者之间无需直接交互,降低了系统的耦合度。
- 异步处理:生产者发送消息后可以继续执行其他任务,消费者可以在合适的时间接收和处理消息。
- 可靠性:通过消息持久化和事务支持,确保消息不会丢失。
- 负载均衡:在有多个消费者的情况下,消息会自动分配给不同的消费者,实现负载均衡。
使用场景
- 任务分配:将任务放入队列,由多个消费者并行处理,提高系统的处理能力。
- 订单处理:确保订单消息只被处理一次,避免重复处理。
- 日志处理:将应用产生的日志发送到队列,由专门的日志处理服务进行分析和存储。
示例代码
以下是一个简单的 ActiveMQ Queue 模式生产者和消费者示例:
生产者代码:
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class ActiveMQSender {
private static final String USERNAME = "admin";
private static final String PASSWORD = "admin";
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String QUEUE_NAME = "MyQueue";
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(QUEUE_NAME);
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
TextMessage message = session.createTextMessage("Hello ActiveMQ!");
producer.send(message);
System.out.println("Sent message: " + message.getText());
session.close();
connection.close();
}
}
消费者代码:
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class ActiveMQReceiver {
private static final String USERNAME = "admin";
private static final String PASSWORD = "admin";
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String QUEUE_NAME = "MyQueue";
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKER_URL);
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue(QUEUE_NAME);
MessageConsumer consumer = session.createConsumer(destination);
while (true) {
TextMessage message = (TextMessage) consumer.receive(1000);
if (message != null) {
System.out.println("Received message: " + message.getText());
} else {
break;
}
}
session.close();
connection.close();
}
}
通过以上代码,生产者可以将消息发送到队列中,消费者可以从队列中接收并处理消息。
ActiveMQ 是 Apache 旗下的一款开源 消息中间件,基于 JMS(Java Message Service,Java 消息服务)规范 实现,支持多种消息模型,其中 队列(Queue) 是其核心功能之一。以下从队列模型、特性、使用场景、操作示例等方面详细介绍 ActiveMQ 中的队列。
一、ActiveMQ 队列的核心概念
1. 队列模型(Queue Model)
- 消息传递方式:基于 点对点(Point-to-Point) 模式,消息生产者(Producer)将消息发送到队列,消费者(Consumer)从队列中获取消息。
- 核心规则:
- 每个消息只能被 一个消费者 接收并处理(即使有多个消费者,消息也只会被其中一个消费)。
- 消息遵循 先进先出(FIFO) 原则,先入队的消息先被消费。
- 消费者可以随时订阅队列,未被消费的消息会持久化存储,直到被消费或过期。
2. 与主题(Topic)的区别
特性 | 队列(Queue) | 主题(Topic) |
---|---|---|
消息模式 | 点对点(一对一) | 发布-订阅(一对多) |
消息消费 | 每个消息仅被一个消费者处理 | 每个消息可被多个消费者处理 |
持久化 | 支持(未消费的消息会保留) | 支持(需消费者提前订阅并设置持久化) |
适用场景 | 任务分配、请求响应等一对一场景 | 通知、广播等一对多场景 |
二、ActiveMQ 队列的关键特性
-
消息持久化
- 确保消息在服务器重启或网络故障后不丢失,默认使用 KahaDB 数据库存储消息,也可配置为 JDBC 或其他存储方式。
- 配置示例(
activemq.xml
):<persistenceAdapter> <kahaDB directory="${activemq.data}/kahadb"/> </persistenceAdapter>
-
负载均衡与并发消费
- 多个消费者可以同时监听同一个队列,ActiveMQ 会通过 轮询(Round Robin) 或 粘性路由(Sticky Session) 等策略分配消息,实现负载均衡。
- 适用于高并发场景(如订单处理、任务分发)。
-
消息优先级
- 支持设置消息优先级(0-9,数值越大优先级越高),高优先级消息会优先被消费。
- 生产者示例(Java):
Message message = session.createTextMessage("Hello ActiveMQ"); message.setJMSPriority(9); // 设置优先级为最高 producer.send(message);
-
消息过滤
- 消费者可以通过 Selector 表达式 过滤消息,仅接收符合条件的消息。
- 示例:消费者只接收属性
type=order
的消息:consumer = session.createConsumer(queue, "type = 'order'");
三、ActiveMQ 队列的使用场景
-
异步任务处理
- 例如用户下单后,将“生成订单详情”“发送通知”等任务放入队列,异步处理以提升系统响应速度。
-
系统解耦
- 不同服务(如用户服务、支付服务)通过队列通信,降低服务间的直接依赖。
-
流量削峰
- 在秒杀、促销等高并发场景中,将请求暂存到队列中,后端服务按处理能力消费,避免系统过载。
-
分布式事务补偿
- 通过队列实现最终一致性(如基于可靠消息的事务方案)。
四、ActiveMQ 队列操作示例(Java)
以下示例基于 ActiveMQ 的 JMS API,需引入依赖:
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.17.1</version> <!-- 最新版本请查看官网 -->
</dependency>
1. 生产者(发送消息到队列)
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
public class QueueProducer {
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String QUEUE_NAME = "my-queue";
public static void main(String[] args) throws JMSException {
// 创建连接工厂
ConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL);
// 创建连接
try (Connection connection = factory.createConnection();
// 启动连接
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建队列
Queue queue = session.createQueue(QUEUE_NAME);
// 创建生产者
MessageProducer producer = session.createProducer(queue)) {
connection.start();
// 发送 5 条消息
for (int i = 1; i <= 5; i++) {
String messageText = "Message " + i;
TextMessage message = session.createTextMessage(messageText);
producer.send(message);
System.out.println("Sent: " + messageText);
}
}
}
}
2. 消费者(从队列接收消息)
public class QueueConsumer {
private static final String BROKER_URL = "tcp://localhost:61616";
private static final String QUEUE_NAME = "my-queue";
public static void main(String[] args) throws JMSException {
ConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL);
try (Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageConsumer consumer = session.createConsumer(queue)) {
connection.start();
// 持续监听队列(此处为简化示例,实际可通过循环或监听器实现)
while (true) {
TextMessage message = (TextMessage) consumer.receive(1000); // 超时时间 1秒
if (message != null) {
System.out.println("Received: " + message.getText());
} else {
break; // 无消息时退出(实际场景中可保持循环监听)
}
}
}
}
}
五、ActiveMQ 队列配置与管理
-
启动 ActiveMQ 服务器
- 下载 ActiveMQ 压缩包,解压后执行
bin/activemq start
(Linux/Mac)或bin/activemq.bat start
(Windows)。 - 访问管理界面:
http://localhost:8161/admin
(默认用户名/密码:admin/admin
),可查看队列状态、消息计数等。
- 下载 ActiveMQ 压缩包,解压后执行
-
配置队列属性
- 在
activemq.xml
中定义队列(如设置持久化、过期时间等):<broker> <destinations> <!-- 定义持久化队列 --> <queue physicalName="my-queue"> <dispatchPolicy> <strictOrderDispatchPolicy/> <!-- 严格按顺序分发 --> </dispatchPolicy> <queueProperties> <entry key="maxQueueSize" value="10000"/> <!-- 最大队列长度 --> <entry key="timeToLive" value="3600000"/> <!-- 消息过期时间(毫秒) --> </queueProperties> </queue> </destinations> </broker>
- 在
六、注意事项
-
消息重复消费
- 若消费者未正确确认消息(如使用
Session.CLIENT_ACKNOWLEDGE
时未调用acknowledge()
),可能导致消息重复消费,需通过业务逻辑幂等性处理。
- 若消费者未正确确认消息(如使用
-
性能优化
- 批量发送消息(
producer.send(Collection<Message>)
)以减少网络开销。 - 使用非持久化队列(
session.createQueue("queueName", false)
)处理非关键消息,提升吞吐量。
- 批量发送消息(
-
监控与告警
- 通过 ActiveMQ 管理界面或集成 Prometheus、Grafana 监控队列积压、消费延迟等指标,设置告警规则。
总结
ActiveMQ 的队列模型是实现分布式系统异步通信和业务解耦的核心工具,适用于需要可靠消息传递、负载均衡和流量控制的场景。通过合理配置持久化、优先级、过滤规则等特性,可以灵活应对不同业务需求。如果需要进一步了解特定功能(如事务消息、集群部署),可随时补充提问!