
本文是博主在梳理 RabbitMQ 知识的过程中,将所遇到和可能会遇到的基础知识记录下来,用作梳理 RabbitMQ 的整体架构和功能的线索文章,通过查找对应的知识能够快速的了解对应的知识而解决相应的问题。
一、核心组件说明
本示例基于 RabbitMQ 默认直连交换机( Default Direct Exchange )实现基础消息通信,展示生产消费模型的核心流程。
- 生产者(Producer):消息创建与发送方
- 消费者(Consumer):消息接收与处理方
- 消息队列(Queue):消息存储容器
- 默认交换机:系统预置直连交换机(名称为空字符串)
二、生产者实现
public class Producer {
// 核心配置参数
private static final String QUEUE_NAME = "my-mq-queue";
private static final String HOST = "10.106.182.54";
private static final String USERNAME = "root";
private static final String PASSWORD = "123456";
private static final String EXCHANGE_NAME = ""; // 使用默认直连交换机
public static void main(String[] args) {
// 1. 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(HOST);
factory.setUsername(USERNAME);
factory.setPassword(PASSWORD);
try (
// 2. 建立TCP连接(自动关闭)
Connection connection = factory.newConnection();
// 3. 创建信道(自动关闭)
Channel channel = connection.createChannel()
) {
// 4. 声明队列(参数需与消费者一致)
Map<String, Object> queueArgs = new HashMap<>();
queueArgs.put("x-message-ttl", 10000); // 消息10秒过期
channel.queueDeclare(QUEUE_NAME,
false, // 非持久化队列
false, // 非排他队列
true, // 自动删除队列(无消费者时自动删除)
queueArgs
);
// 5. 构造并发送消息
String message = "Hello, How are you";
channel.basicPublish(
EXCHANGE_NAME, // 使用默认交换机
QUEUE_NAME, // 路由键=队列名(直连交换机特性)
null, // 消息属性(优先级、过期时间等)
message.getBytes()
);
System.out.println("[Producer] 消息发送成功");
} catch (IOException e) {
throw new RuntimeException("消息发送失败", e);
}
}
}
三、消费者实现
public class Consumer {
// 配置与生产者保持严格一致
public static final String QUEUE_NAME = "my-mq-queue";
// ...其他配置同生产者...
public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(HOST);
factory.setUsername(USERNAME);
factory.setPassword(PASSWORD);
try {
// 建立长连接
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 声明队列(参数必须与生产者完全一致)
Map<String, Object> queueArgs = new HashMap<>();
queueArgs.put("x-message-ttl", 10000);
channel.queueDeclare(QUEUE_NAME, false, false, true, queueArgs);
// 创建消息回调处理器
DeliverCallback callback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.printf("[Consumer] 接收到消息 | 标签:%s | 内容:%s%n",
delivery.getEnvelope().getDeliveryTag(), message);
};
// 启动消息监听(推模式)
channel.basicConsume(
QUEUE_NAME,
true, // 自动确认(收到即确认)
callback,
consumerTag -> {}
);
System.out.println("[Consumer] 已启动消息监听");
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、关键代码解析
1、队列声明(queueDeclare)
channel.queueDeclare(QUEUE_NAME, durable, exclusive, autoDelete, arguments);
- durable:队列持久化(服务重启后保留)
- exclusive:排他队列(仅当前连接可见,连接关闭后自动删除)
- autoDelete:自动删除(当最后一个消费者取消订阅时删除)
- arguments:扩展参数(消息TTL、死信配置等)
2、消息发布(basicPublish)
channel.basicPublish(exchange, routingKey, props, body);
- 使用默认交换机时,也就是直连交换机,
routingKey必须与队列名一致 - 消息属性(props)可设置优先级、过期时间等元信息
3、消息消费模式
- 推模式(Push):
basicConsume实时接收消息(推荐) - 拉模式(Pull):
basicGet主动轮询获取消息
五、注意事项
- 队列参数一致性:生产者和消费者声明队列时参数必须完全一致,否则会抛出参数不匹配异常,建议将队列配置参数提取为常量类统一管理。
- 使用
try-with-resources自动关闭连接和通道,消费者建议保持长连接,避免频繁创建销毁。 - 消息确认机制:示例使用自动确认(autoAck=true),存在消息丢失风险,生产环境建议采用手动确认。
channel.basicConsume(QUEUE_NAME, false, callback, ...); // 处理完成后手动确认 channel.basicAck(deliveryTag, false); - 默认交换机特性:将消息直接路由到与routingKey同名的队列,队列自动绑定到默认交换机(routingKey=队列名)。
六、扩展实践建议
-
消息持久化:
// 消息属性设置持久化 AMQP.BasicProperties props = new AMQP.BasicProperties.Builder() .deliveryMode(2) // 持久化消息 .build(); -
QoS预取控制:
channel.basicQos(10); // 每次预取10条消息 -
死信队列配置:
Map<String, Object> args = new HashMap<>(); args.put("x-dead-letter-exchange", "dlx.exchange"); channel.queueDeclare("business.queue", true, false, false, args);
本示例展示了 RabbitMQ 最基础的通信模型,实际生产环境中建议根据业务需求选择合适的交换机类型、完善消息确认机制,并结合 Spring AMQP 等框架进行工程化实现。
511

被折叠的 条评论
为什么被折叠?



