学习时间: 4-5小时
学习目标: 掌握消息队列的使用,学会使用RabbitMQ和Kafka,理解异步处理模式
详细学习清单
✅ 第一部分:消息队列基础概念(60分钟)
1. 消息队列的作用与优势
消息队列基础分析
java
// MessageQueueBasics.java
package com.example.demo.messagequeue;
import java.util.ArrayList;
import java.util.List;
public class MessageQueueBasics {
public static class QueueAdvantage {
private String name;
private String description;
private String example;
private String benefit;
public QueueAdvantage(String name, String description, String example, String benefit) {
this.name = name;
this.description = description;
this.example = example;
this.benefit = benefit;
}
// Getter方法
public String getName() { return name; }
public String getDescription() { return description; }
public String getExample() { return example; }
public String getBenefit() { return benefit; }
}
public static void main(String[] args) {
List<QueueAdvantage> advantages = new ArrayList<>();
// 异步处理
advantages.add(new QueueAdvantage(
"异步处理",
"发送方不需要等待接收方处理完成",
"用户下单后立即返回成功,库存扣减在后台异步进行",
"提高系统响应速度,改善用户体验"
));
// 解耦服务
advantages.add(new QueueAdvantage(
"服务解耦",
"服务间通过消息通信,不直接依赖",
"订单服务发送消息,库存服务、支付服务独立消费",
"降低系统耦合度,便于独立开发和部署"
));
// 流量削峰
advantages.add(new QueueAdvantage(
"流量削峰",
"突发流量通过队列缓冲,平滑处理",
"双11秒杀活动,大量请求进入队列,系统按能力处理",
"保护系统稳定性,避免过载崩溃"
));
// 可靠性保证
advantages.add(new QueueAdvantage(
"可靠性保证",
"消息持久化,确保不丢失",
"支付成功后发送通知,即使系统重启也能保证通知发送",
"提高系统可靠性,保证数据完整性"
));
System.out.println("=== 消息队列主要优势 ===");
for (QueueAdvantage advantage : advantages) {
System.out.println("\n优势名称: " + advantage.getName());
System.out.println("详细描述: " + advantage.getDescription());
System.out.println("具体示例: " + advantage.getExample());
System.out.println("带来好处: " + advantage.getBenefit());
}
}
}
2. 消息队列模式分析
消息队列模式详解
java
// MessageQueuePatterns.java
package com.example.demo.messagequeue;
import java.util.HashMap;
import java.util.Map;
public class MessageQueuePatterns {
public static class QueuePattern {
private String name;
private String description;
private String useCase;
private String implementation;
public QueuePattern(String name, String description, String useCase, String implementation) {
this.name = name;
this.description = description;
this.useCase = useCase;
this.implementation = implementation;
}
// Getter方法
public String getName() { return name; }
public String getDescription() { return description; }
public String getUseCase() { return useCase; }
public String getImplementation() { return implementation; }
}
public static void main(String[] args) {
Map<String, QueuePattern> patterns = new HashMap<>();
// 点对点模式
patterns.put("P2P", new QueuePattern(
"点对点模式 (Point-to-Point)",
"一个生产者对应一个消费者,消息被消费后从队列中移除",
"订单处理、邮件发送、短信通知",
"使用Queue,消息只能被一个消费者处理"
));
// 发布订阅模式
patterns.put("PubSub", new QueuePattern(
"发布订阅模式 (Publish-Subscribe)",
"一个生产者对应多个消费者,每个消费者都能收到消息副本",
"系统通知、日志收集、事件广播",
"使用Topic,消息被广播到所有订阅者"
));
// 请求响应模式
patterns.put("RequestResponse", new QueuePattern(
"请求响应模式 (Request-Response)",
"生产者发送请求,消费者处理并返回响应",
"RPC调用、任务分发、查询请求",
"使用临时队列和关联ID实现双向通信"
));
// 工作队列模式
patterns.put("WorkQueue", new QueuePattern(
"工作队列模式 (Work Queue)",
"多个消费者竞争处理队列中的任务",
"图片处理、文件转换、批量计算",
"使用轮询或公平分发策略分配任务"
));
System.out.println("=== 消息队列主要模式 ===");
for (Map.Entry<String, QueuePattern> entry : patterns.entrySet()) {
QueuePattern pattern = entry.getValue();
System.out.println("\n模式类型: " + entry.getKey() + " - " + pattern.getName());
System.out.println("模式描述: " + pattern.getDescription());
System.out.println("使用场景: " + pattern.getUseCase());
System.out.println("实现方式: " + pattern.getImplementation());
}
}
}
✅ 第二部分:RabbitMQ集成与使用(90分钟)
1. RabbitMQ配置与依赖
Maven依赖配置
xml
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>message-queue-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>rabbitmq-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
RabbitMQ配置
yaml
# application.yml
server:
port: 8080
spring:
application:
name: rabbitmq-service
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
# 连接池配置
connection-timeout: 15000
requested-heart-beat: 30
# 发布确认
publisher-confirm-type: correlated
publisher-returns: true
# 消费者配置
listener:
simple:
acknowledge-mode: manual
prefetch: 1
retry:
enabled: true
initial-interval: 1000
max-attempts: 3
max-interval: 10000
multiplier: 1.0
default-requeue-rejected: false
# 自定义配置
rabbitmq:
exchange:
order: order.exchange
notification: notification.exchange
dead-letter: dead.letter.exchange
queue:
order-created: order.created.queue
order-paid: order.paid.queue
order-cancelled: order.cancelled.queue
notification: notification.queue
dead-letter: dead.letter.queue
routing-key:
order-created: order.created
order-paid: order.paid
order-cancelled: order.cancelled
notification: notification
2. RabbitMQ配置类
RabbitMQ配置类
java
// RabbitMQConfig.java
package com.example.rabbitmq.config;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
@Value("${rabbitmq.exchange.order}")
private String orderExchange;
@Value("${rabbitmq.exchange.notification}")
private String notificationExchange;
@Value("${rabbitmq.exchange.dead-letter}")
private String deadLetterExchange;
@Value("${rabbitmq.queue.order-created}")
private String orderCreatedQueue;
@Value("${rabbitmq.queue.order-paid}")
private String orderPaidQueue;
@Value("${rabbitmq.queue.order-cancelled}")
private String orderCancelledQueue;
@Value("${rabbitmq.queue.notification}")
private String notificationQueue;
@Value("${rabbitmq.queue.dead-letter}")
private String deadLetterQueue;
/**
* 消息转换器
*/
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
/**
* RabbitTemplate配置
*/
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(jsonMessageConverter());
// 发布确认回调
template.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
System.out.println("消息发送成功: " + correlationData);
} else {
System.err.println("消息发送失败: " + cause);
}
});
// 返回回调
template.setReturnsCallback(returned -> {
System.err.println("消息被退回: " + returned);
});
return template;
}
/**
* 订单交换机
*/
@Bean
public DirectExchange orderExchange() {
return new DirectExchange(orderExchange);
}
/**
* 通知交换机
*/
@Bean
public FanoutExchange notificationExchange() {
return new FanoutExchange(notificationExchange);
}
/**
* 死信交换机
*/
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange(deadLetterExchange);
}
/**
* 订单创建队列
*/
@Bean
public Queue orderCreatedQueue() {
return QueueBuilder.durable(orderCreatedQueue)
.withArgument("x-dead-letter-exchange", deadLetterExchange)
.withArgument("x-dead-letter-routing-key", "dead.letter")
.withArgument("x-message-ttl", 300000) // 5分钟过期
.build();
}
/**
* 订单支付队列
*/
@Bean
public Queue orderPaidQueue() {
return QueueBuilder.durable(orderPaidQueue)
.withArgument("x-dead-letter-exchange", deadLetterExchange)
.withArgument("x-dead-letter-routing-key", "dead.letter")
.build();
}
/**
* 订单取消队列
*/
@Bean
public Queue orderCancelledQueue() {
return QueueBuilder.durable(orderCancelledQueue)
.withArgument("x-dead-letter-exchange", deadLetterExchange)
.withArgument("x-dead-letter-routing-key", "dead.letter")
.build();
}
/**
* 通知队列
*/
@Bean
public Queue notificationQueue() {
return QueueBuilder.durable(notificationQueue)
.withArgument("x-dead-letter-exchange", deadLetterExchange)
.withArgument("x-dead-letter-routing-key", "dead.letter")
.build();
}
/**
* 死信队列
*/
@Bean
public Queue deadLetterQueue() {
return QueueBuilder.durable(deadLetterQueue).build();
}
/**
* 绑定订单创建队列到交换机
*/
@Bean
public Binding orderCreatedBinding() {
return BindingBuilder.bind(orderCreatedQueue())
.to(orderExchange())
.with("order.created");
}
/**
* 绑定订单支付队列到交换机
*/
@Bean
public Binding orderPaidBinding() {
return BindingBuilder.bind(orderPaidQueue())
.to(orderExchange())
.with("order.paid");
}
/**
* 绑定订单取消队列到交换机
*/
@Bean
public Binding orderCancelledBinding() {
return BindingBuilder.bind(orderCancelledQueue())
.to(orderExchange())
.with("order.cancelled");
}
/**
* 绑定通知队列到交换机
*/
@Bean
public Binding notificationBinding() {
return BindingBuilder.bind(notificationQueue())
.to(notificationExchange());
}
/**
* 绑定死信队列到交换机
*/
@Bean
public Binding deadLetterBinding() {
return BindingBuilder.bind(deadLetterQueue())
.to(deadLetterExchange())
.with("dead.letter");
}
}
3. 消息实体类
订单消息实体
java
// OrderMessage.java
package com.example.rabbitmq.model;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class OrderMessage {
private String messageId;
private String orderNumber;
private Long userId;
private Long productId;
private Integer quantity;
private BigDecimal amount;
private String status;
private LocalDateTime createTime;
private String source;
private String traceId;
public OrderMessage() {
this.messageId = java.util.UUID.randomUUID().toString();
this.createTime = LocalDateTime.now();
}
public OrderMessage(String orderNumber, Long userId, Long productId,
Integer quantity, BigDecimal amount, String status) {
this();
this.orderNumber = orderNumber;
this.userId = userId;
this.productId = productId;
this.quantity = quantity;
this.amount = amount;
this.status = status;
}
}
通知消息实体
java
// NotificationMessage.java
package com.example.rabbitmq.model;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
@Data
public class NotificationMessage {
private String messageId;
private String type; // EMAIL, SMS, PUSH, WEBHOOK
private String title;
private String content;
private String recipient; // 邮箱、手机号、用户ID等
private Map<String, Object> data;
private Integer priority; // 1-低, 2-中, 3-高
private LocalDateTime createTime;
private LocalDateTime scheduledTime;
private String status; // PENDING, SENT, FAILED
public NotificationMessage() {
this.messageId = java.util.UUID.randomUUID().toString();
this.createTime = LocalDateTime.now();
this.status = "PENDING";
this.priority = 2;
}
public NotificationMessage(String type, String title, String content, String recipient) {
this();
this.type = type;
this.title = title;
this.content = content;
this.recipient = recipient;
}
}
✅ 第三部分:消息生产者与消费者(90分钟)
1. 消息生产者服务
订单消息生产者
java
// OrderMessageProducer.java
package com.example.rabbitmq.producer;
import com.example.rabbitmq.model.OrderMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Slf4j
@Service
public class OrderMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Value("${rabbitmq.exchange.order}")
private String orderExchange;
@Value("${rabbitmq.exchange.notification}")
private String notificationExchange;
/**
* 发送订单创建消息
*/
public void sendOrderCreated(OrderMessage orderMessage) {
try {
String routingKey = "order.created";
rabbitTemplate.convertAndSend(orderExchange, routingKey, orderMessage);
log.info("订单创建消息发送成功: {}", orderMessage.getOrderNumber());
} catch (Exception e) {
log.error("订单创建消息发送失败: {}", orderMessage.getOrderNumber(), e);
throw new RuntimeException("消息发送失败", e);
}
}
/**
* 发送订单支付消息
*/
public void sendOrderPaid(OrderMessage orderMessage) {
try {
String routingKey = "order.paid";
rabbitTemplate.convertAndSend(orderExchange, routingKey, orderMessage);
log.info("订单支付消息发送成功: {}", orderMessage.getOrderNumber());
} catch (Exception e) {
log.error("订单支付消息发送失败: {}", orderMessage.getOrderNumber(), e);
throw new RuntimeException("消息发送失败", e);
}
}
/**
* 发送订单取消消息
*/
public void sendOrderCancelled(OrderMessage orderMessage) {
try {
String routingKey = "order.cancelled";
rabbitTemplate.convertAndSend(orderExchange, routingKey, orderMessage);
log.info("订单取消消息发送成功: {}", orderMessage.getOrderNumber());
} catch (Exception e) {
log.error("订单取消消息发送失败: {}", orderMessage.getOrderNumber(), e);
throw new RuntimeException("消息发送失败", e);
}
}
/**
* 发送延迟消息
*/
public void sendDelayedMessage(OrderMessage orderMessage, long delayMillis) {
try {
// 使用死信队列实现延迟消息
String routingKey = "order.delayed";
rabbitTemplate.convertAndSend(orderExchange, routingKey, orderMessage, message -> {
message.getMessageProperties().setExpiration(String.valueOf(delayMillis));
return message;
});
log.info("延迟消息发送成功: {}, 延迟: {}ms", orderMessage.getOrderNumber(), delayMillis);
} catch (Exception e) {
log.error("延迟消息发送失败: {}", orderMessage.getOrderNumber(), e);
throw new RuntimeException("延迟消息发送失败", e);
}
}
/**
* 发送批量消息
*/
public void sendBatchMessages(List<OrderMessage> messages) {
try {
for (OrderMessage message : messages) {
String routingKey = "order.batch";
rabbitTemplate.convertAndSend(orderExchange, routingKey, message);
}
log.info("批量消息发送成功,数量: {}", messages.size());
} catch (Exception e) {
log.error("批量消息发送失败", e);
throw new RuntimeException("批量消息发送失败", e);
}
}
}
通知消息生产者
java
// NotificationMessageProducer.java
package com.example.rabbitmq.producer;
import com.example.rabbitmq.model.NotificationMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class NotificationMessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
@Value("${rabbitmq.exchange.notification}")
private String notificationExchange;
/**
* 发送通知消息
*/
public void sendNotification(NotificationMessage notification) {
try {
rabbitTemplate.convertAndSend(notificationExchange, "", notification);
log.info("通知消息发送成功: {}", notification.getMessageId());
} catch (Exception e) {
log.error("通知消息发送失败: {}", notification.getMessageId(), e);
throw new RuntimeException("通知消息发送失败", e);
}
}
/**
* 发送批量通知
*/
public void sendBatchNotifications(List<NotificationMessage> notifications) {
try {
for (NotificationMessage notification : notifications) {
rabbitTemplate.convertAndSend(notificationExchange, "", notification);
}
log.info("批量通知发送成功,数量: {}", notifications.size());
} catch (Exception e) {
log.error("批量通知发送失败", e);
throw new RuntimeException("批量通知发送失败", e);
}
}
/**
* 发送优先级通知
*/
public void sendPriorityNotification(NotificationMessage notification) {
try {
// 根据优先级设置不同的路由键
String routingKey = "notification.priority." + notification.getPriority();
rabbitTemplate.convertAndSend(notificationExchange, routingKey, notification);
log.info("优先级通知发送成功: {}, 优先级: {}", notification.getMessageId(), notification.getPriority());
} catch (Exception e) {
log.error("优先级通知发送失败: {}", notification.getMessageId(), e);
throw new RuntimeException("优先级通知发送失败", e);
}
}
}
2. 消息消费者服务
订单消息消费者
java
// OrderMessageConsumer.java
package com.example.rabbitmq.consumer;
import com.example.rabbitmq.model.OrderMessage;
import com.example.rabbitmq.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
import com.rabbitmq.client.Channel;
import java.io.IOException;
@Slf4j
@Service
public class OrderMessageConsumer {
@Autowired
private OrderService orderService;
/**
* 消费订单创建消息
*/
@RabbitListener(queues = "${rabbitmq.queue.order-created}")
public void consumeOrderCreated(OrderMessage orderMessage,
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
log.info("收到订单创建消息: {}", orderMessage.getOrderNumber());
// 处理订单创建逻辑
orderService.processOrderCreated(orderMessage);
// 手动确认消息
channel.basicAck(deliveryTag, false);
log.info("订单创建消息处理成功: {}", orderMessage.getOrderNumber());
} catch (Exception e) {
log.error("订单创建消息处理失败: {}", orderMessage.getOrderNumber(), e);
try {
// 消息处理失败,拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
} catch (IOException ioException) {
log.error("消息拒绝失败", ioException);
}
}
}
/**
* 消费订单支付消息
*/
@RabbitListener(queues = "${rabbitmq.queue.order-paid}")
public void consumeOrderPaid(OrderMessage orderMessage,
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
log.info("收到订单支付消息: {}", orderMessage.getOrderNumber());
// 处理订单支付逻辑
orderService.processOrderPaid(orderMessage);
// 手动确认消息
channel.basicAck(deliveryTag, false);
log.info("订单支付消息处理成功: {}", orderMessage.getOrderNumber());
} catch (Exception e) {
log.error("订单支付消息处理失败: {}", orderMessage.getOrderNumber(), e);
try {
// 消息处理失败,拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
} catch (IOException ioException) {
log.error("消息拒绝失败", ioException);
}
}
}
/**
* 消费订单取消消息
*/
@RabbitListener(queues = "${rabbitmq.queue.order-cancelled}")
public void consumeOrderCancelled(OrderMessage orderMessage,
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
log.info("收到订单取消消息: {}", orderMessage.getOrderNumber());
// 处理订单取消逻辑
orderService.processOrderCancelled(orderMessage);
// 手动确认消息
channel.basicAck(deliveryTag, false);
log.info("订单取消消息处理成功: {}", orderMessage.getOrderNumber());
} catch (Exception e) {
log.error("订单取消消息处理失败: {}", orderMessage.getOrderNumber(), e);
try {
// 消息处理失败,拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
} catch (IOException ioException) {
log.error("消息拒绝失败", ioException);
}
}
}
}
通知消息消费者
java
// NotificationMessageConsumer.java
package com.example.rabbitmq.consumer;
import com.example.rabbitmq.model.NotificationMessage;
import com.example.rabbitmq.service.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
import com.rabbitmq.client.Channel;
import java.io.IOException;
@Slf4j
@Service
public class NotificationMessageConsumer {
@Autowired
private NotificationService notificationService;
/**
* 消费通知消息
*/
@RabbitListener(queues = "${rabbitmq.queue.notification}")
public void consumeNotification(NotificationMessage notification,
Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
log.info("收到通知消息: {}, 类型: {}", notification.getMessageId(), notification.getType());
// 处理通知逻辑
notificationService.processNotification(notification);
// 手动确认消息
channel.basicAck(deliveryTag, false);
log.info("通知消息处理成功: {}", notification.getMessageId());
} catch (Exception e) {
log.error("通知消息处理失败: {}", notification.getMessageId(), e);
try {
// 消息处理失败,拒绝消息并重新入队
channel.basicNack(deliveryTag, false, true);
} catch (IOException ioException) {
log.error("消息拒绝失败", ioException);
}
}
}
/**
* 消费死信消息
*/
@RabbitListener(queues = "${rabbitmq.queue.dead-letter}")
public void consumeDeadLetter(Message message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
log.warn("收到死信消息: {}", message);
// 处理死信消息逻辑
notificationService.processDeadLetter(message);
// 手动确认消息
channel.basicAck(deliveryTag, false);
log.info("死信消息处理成功");
} catch (Exception e) {
log.error("死信消息处理失败", e);
try {
// 死信消息处理失败,拒绝消息
channel.basicNack(deliveryTag, false, false);
} catch (IOException ioException) {
log.error("死信消息拒绝失败", ioException);
}
}
}
}
✅ 第四部分:异步处理与任务调度(60分钟)
1. 异步任务配置
异步配置类
java
// AsyncConfig.java
package com.example.rabbitmq.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class AsyncConfig {
/**
* 异步任务执行器
*/
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数
executor.setCorePoolSize(10);
// 最大线程数
executor.setMaxPoolSize(20);
// 队列容量
executor.setQueueCapacity(500);
// 线程空闲时间
executor.setKeepAliveSeconds(60);
// 线程名前缀
executor.setThreadNamePrefix("AsyncTask-");
// 拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
// 等待时间
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
/**
* 消息处理执行器
*/
@Bean("messageExecutor")
public Executor messageExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("MessageTask-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}
2. 异步任务服务
异步订单处理服务
java
// AsyncOrderService.java
package com.example.rabbitmq.service;
import com.example.rabbitmq.model.OrderMessage;
import com.example.rabbitmq.producer.OrderMessageProducer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Slf4j
@Service
public class AsyncOrderService {
@Autowired
private OrderMessageProducer orderMessageProducer;
@Autowired
private NotificationService notificationService;
/**
* 异步处理订单创建
*/
@Async("taskExecutor")
public CompletableFuture<String> processOrderAsync(OrderMessage orderMessage) {
try {
log.info("开始异步处理订单: {}", orderMessage.getOrderNumber());
// 模拟处理时间
Thread.sleep(2000);
// 发送订单创建消息
orderMessageProducer.sendOrderCreated(orderMessage);
// 发送通知
notificationService.sendOrderCreatedNotification(orderMessage);
log.info("订单异步处理完成: {}", orderMessage.getOrderNumber());
return CompletableFuture.completedFuture("SUCCESS");
} catch (Exception e) {
log.error("订单异步处理失败: {}", orderMessage.getOrderNumber(), e);
return CompletableFuture.completedFuture("FAILED");
}
}
/**
* 异步批量处理订单
*/
@Async("taskExecutor")
public CompletableFuture<Integer> processBatchOrdersAsync(List<OrderMessage> orders) {
try {
log.info("开始异步批量处理订单,数量: {}", orders.size());
int successCount = 0;
for (OrderMessage order : orders) {
try {
// 处理单个订单
orderMessageProducer.sendOrderCreated(order);
successCount++;
} catch (Exception e) {
log.error("订单处理失败: {}", order.getOrderNumber(), e);
}
}
log.info("批量订单处理完成,成功: {}, 失败: {}", successCount, orders.size() - successCount);
return CompletableFuture.completedFuture(successCount);
} catch (Exception e) {
log.error("批量订单处理失败", e);
return CompletableFuture.completedFuture(0);
}
}
/**
* 异步处理订单支付
*/
@Async("messageExecutor")
public CompletableFuture<Boolean> processPaymentAsync(OrderMessage orderMessage) {
try {
log.info("开始异步处理订单支付: {}", orderMessage.getOrderNumber());
// 模拟支付处理时间
Thread.sleep(3000);
// 发送支付成功消息
orderMessageProducer.sendOrderPaid(orderMessage);
// 发送支付成功通知
notificationService.sendPaymentSuccessNotification(orderMessage);
log.info("订单支付处理完成: {}", orderMessage.getOrderNumber());
return CompletableFuture.completedFuture(true);
} catch (Exception e) {
log.error("订单支付处理失败: {}", orderMessage.getOrderNumber(), e);
return CompletableFuture.completedFuture(false);
}
}
}
3. 定时任务服务
定时任务配置
java
// ScheduledTaskService.java
package com.example.rabbitmq.service;
import com.example.rabbitmq.producer.OrderMessageProducer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
@Service
public class ScheduledTaskService {
@Autowired
private OrderMessageProducer orderMessageProducer;
@Autowired
private OrderService orderService;
/**
* 定时清理过期订单(每分钟执行一次)
*/
@Scheduled(fixedRate = 60000)
public void cleanExpiredOrders() {
try {
log.info("开始清理过期订单,时间: {}", LocalDateTime.now());
// 获取过期订单
List<OrderMessage> expiredOrders = orderService.getExpiredOrders();
if (!expiredOrders.isEmpty()) {
// 发送订单取消消息
for (OrderMessage order : expiredOrders) {
orderMessageProducer.sendOrderCancelled(order);
}
log.info("过期订单清理完成,数量: {}", expiredOrders.size());
} else {
log.info("没有过期订单需要清理");
}
} catch (Exception e) {
log.error("清理过期订单失败", e);
}
}
/**
* 定时发送提醒消息(每天上午9点执行)
*/
@Scheduled(cron = "0 0 9 * * ?")
public void sendDailyReminders() {
try {
log.info("开始发送每日提醒消息,时间: {}", LocalDateTime.now());
// 获取需要提醒的订单
List<OrderMessage> reminderOrders = orderService.getOrdersNeedingReminder();
if (!reminderOrders.isEmpty()) {
// 发送提醒消息
for (OrderMessage order : reminderOrders) {
// 发送延迟提醒消息
orderMessageProducer.sendDelayedMessage(order, 300000); // 5分钟后发送
}
log.info("每日提醒消息发送完成,数量: {}", reminderOrders.size());
} else {
log.info("没有需要提醒的订单");
}
} catch (Exception e) {
log.error("发送每日提醒消息失败", e);
}
}
/**
* 定时统计消息队列状态(每5分钟执行一次)
*/
@Scheduled(fixedRate = 300000)
public void monitorQueueStatus() {
try {
log.info("开始监控消息队列状态,时间: {}", LocalDateTime.now());
// 获取队列统计信息
QueueStats stats = getQueueStats();
log.info("队列状态监控 - 总消息数: {}, 待处理: {}, 处理中: {}, 已完成: {}",
stats.getTotalMessages(),
stats.getPendingMessages(),
stats.getProcessingMessages(),
stats.getCompletedMessages());
} catch (Exception e) {
log.error("监控消息队列状态失败", e);
}
}
/**
* 队列统计信息
*/
private QueueStats getQueueStats() {
// 这里应该调用RabbitMQ管理API获取实际统计信息
// 为了演示,返回模拟数据
QueueStats stats = new QueueStats();
stats.setTotalMessages(1000);
stats.setPendingMessages(150);
stats.setProcessingMessages(50);
stats.setCompletedMessages(800);
return stats;
}
/**
* 队列统计信息类
*/
public static class QueueStats {
private int totalMessages;
private int pendingMessages;
private int processingMessages;
private int completedMessages;
// Getter和Setter方法
public int getTotalMessages() { return totalMessages; }
public void setTotalMessages(int totalMessages) { this.totalMessages = totalMessages; }
public int getPendingMessages() { return pendingMessages; }
public void setPendingMessages(int pendingMessages) { this.pendingMessages = pendingMessages; }
public int getProcessingMessages() { return processingMessages; }
public void setProcessingMessages(int processingMessages) { this.processingMessages = processingMessages; }
public int getCompletedMessages() { return completedMessages; }
public void setCompletedMessages(int completedMessages) { this.completedMessages = completedMessages; }
}
}
🎯 今日学习总结
1. 掌握的核心技能
- ✅ 消息队列基础概念与优势
- ✅ RabbitMQ配置与集成
- ✅ 消息生产者与消费者实现
- ✅ 异步任务处理与调度
- ✅ 消息队列监控与管理
2. 消息队列核心概念
- 异步处理:提高系统响应速度
- 服务解耦:降低系统耦合度
- 流量削峰:保护系统稳定性
- 可靠性保证:消息持久化存储
3. RabbitMQ主要特性
- 多种交换机类型:Direct、Fanout、Topic
- 消息确认机制:发布确认、消费者确认
- 死信队列:处理失败消息
- 延迟消息:定时任务支持
- 优先级队列:重要消息优先处理
4. 异步处理模式
- @Async注解:Spring异步任务支持
- 线程池配置:自定义执行器
- CompletableFuture:异步结果处理
- 定时任务:@Scheduled注解使用
5. 下一步学习方向
- Kafka消息队列使用
- 消息幂等性处理
- 分布式锁实现
- 缓存策略优化
- 性能监控与调优
学习建议
- 环境搭建:安装RabbitMQ,配置开发环境
- 基础练习:实现简单的消息发送和接收
- 模式理解:深入理解不同消息队列模式
- 异常处理:学会处理消息处理失败的情况
- 性能优化:理解消息队列的性能调优策略