19de7e24ec
从 docs-local 迁移以下文档: - backend/guides/: AI开发环境配置、Nacos配置、GitNexus指南、OpenCode工作流等 - backend/templates/: Superpowers设计模板、计划模板、审查清单 - backend/config-templates/: 应用配置模板、Nacos配置 - backend/design/: 数据库表结构规划 - backend/specs/: 项目文档治理、MQ统一推送设计 - backend/: 代码分析报告、Feign分析报告、文档治理报告 - frontend/design/: Admin-UI分模块打包设计
8.7 KiB
8.7 KiB
MQ 统一推送入口设计文档
设计日期: 2026-06-04 版本: v1.0 状态: 已批准 目标: 创建统一消息队列推送入口 MqClient,封装多 Provider 路由、Action 注入、异常兜底,对标 spring-rui MqDefaultClient
一、背景与目标
1.1 现状分析
当前项目已有基础 MQ 能力:
MqService接口:提供send()方法,面向业务开发者直接使用Message<T>模型:含 id, topic, payload, headers, timestamp, retryCountRedisMqService/RabbitMqService:分别基于 Redis Pub/Sub 和 RabbitMQ 的实现MqTopic注解:用于方法级消息订阅
存在的问题:
- 缺乏统一推送门面:业务代码需要直接注入
MqService并选择实现,无法自动按 Provider 路由 - 无 Provider 抽象:无法在多环境(开发用 Redis、生产用 RabbitMQ)间平滑切换
- 无 Action 语义:消息缺乏"添加/删除/更新"等业务动作标识
- 异常处理分散:各实现自行处理异常,缺乏统一兜底
1.2 目标定义
- 创建
MqClient门面类,作为业务层唯一推送入口 - 引入
MqPublisherProvider 接口,实现多 MQ 后端自动路由 - 扩展
Message模型,支持 action、provider、exchange、delay 等高级字段 - 保持现有
MqService接口不变,确保向后兼容 - 所有推送操作统一异常捕获和日志记录
二、详细设计
2.1 整体架构
┌─────────────────────────────────────────────────────────────┐
│ 业务层 (Business) │
│ MqClient.publish(...) │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ MqClient (门面/统一入口) │
│ · 自动从 Spring 容器获取所有 MqPublisher 实现 │
│ · 按 support(MqProvider) 过滤匹配的 Publisher │
│ · 自动注入 action 到 payload │
│ · 统一 try-catch + 日志 │
└──────────────────────────┬──────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ RedisMqPublisher │ │ RabbitMqPublisher│ │ FutureProvider │
│ (Redis实现) │ │ (RabbitMQ实现) │ │ (可扩展) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
2.2 核心组件
| 组件 | 职责 | 位置 |
|---|---|---|
MqClient |
统一推送门面,业务层唯一入口 | rui-common-mq |
MqPublisher |
Provider 能力接口,定义 support + publish | rui-common-mq |
MqProvider |
Provider 枚举(RABBITMQ, REDIS) | rui-common-mq |
MqProperties |
配置属性(默认 provider、topic prefix) | rui-common-mq |
MqAction |
消息动作枚举(ADDED, DELETED 等) | rui-common-mq |
Message<T> |
扩展后的消息模型 | rui-common-mq |
2.3 数据流
启动阶段 (一次)
│
▼
Spring 注入 List<MqPublisher> → 遍历注册到 EnumMap
│
▼
publisherMap = { RABBITMQ: RabbitMqPublisher, REDIS: RedisMqPublisher }
运行时 (每次 publish)
│
▼
MqClient.publish(String topic, MqAction action, T payload)
│
├─ 1. 构造 Message<T>
├─ 2. 若 action != NONE,将 action 序列化后注入 payload
├─ 3. 若 message.provider == null,使用 MqProperties 默认值
├─ 4. publisherMap.get(provider) → O(1) 直接取到 Publisher
├─ 5. 调用 publisher.publish(message)
└─ 6. catch Exception → log.error,不抛异常
2.4 接口设计
MqClient(门面类)
采用构造器注入 + 启动预构建 EnumMap,避免运行时遍历:
@Component
@Slf4j
public class MqClient {
private final MqProperties properties;
private final EnumMap<MqProvider, MqPublisher> publisherMap = new EnumMap<>(MqProvider.class);
public MqClient(MqProperties properties, List<MqPublisher> publishers) {
this.properties = properties;
for (MqPublisher p : publishers) {
publisherMap.put(p.getProvider(), p); // O(1) 注册
}
}
/** 使用默认 Provider 推送 */
public <T> void publish(String topic, T payload);
/** 使用默认 Provider 推送,带 Action */
public <T> void publish(String topic, MqAction action, T payload);
/** 指定 Provider 推送 */
public <T> void publish(MqProvider provider, String topic, T payload);
/** 指定 Provider 推送,带 Action */
public <T> void publish(MqProvider provider, String topic, MqAction action, T payload);
/** 完整 Message 推送 */
public <T> void publish(Message<T> message);
private MqPublisher resolve(MqProvider provider) {
return publisherMap.get(provider); // O(1) 查找
}
}
MqPublisher(Provider 接口)
public interface MqPublisher {
/** 返回该 Publisher 支持的 Provider 类型 */
MqProvider getProvider();
/** 基础推送 */
<T> void publish(String topic, T payload);
/** 完整消息推送 */
<T> void publish(Message<T> message);
}
MqProvider(枚举)
public enum MqProvider {
RABBITMQ,
REDIS
}
MqProperties(配置)
@ConfigurationProperties(prefix = "mq")
@Data
public class MqProperties {
private MqProvider provider = MqProvider.RABBITMQ;
private String prefix = "rui";
public String enTopic(String topic) { ... }
public String deTopic(String topic) { ... }
}
MqAction(动作枚举,精简版)
public enum MqAction {
NONE, ADDED, DELETED, UPDATED, CREATED,
CANCEL, ENABLED, SUCCESSFUL, FAILURE
}
2.5 扩展现有实现
RedisMqService 调整:
- 实现
MqPublisher接口 support(MqProvider.REDIS)返回 truepublish()复用现有send()逻辑
RabbitMqService 调整:
- 实现
MqPublisher接口 support(MqProvider.RABBITMQ)返回 truepublish()复用现有send()逻辑
2.6 错误处理
- 异常策略:
MqClient所有 publish 方法统一 try-catch,记录 error 日志,不抛异常给业务层 - Provider 不匹配:若找不到支持该 Provider 的 Publisher,记录 warn 日志
- Payload 为空:自动创建空 JSON 对象
{}
三、验收标准
MqClient可正常注入并调用publish()发送消息- 通过配置
mq.provider=redis可自动切换到 Redis 实现 publish(topic, MqAction.ADDED, payload)发送的消息包含 action 字段- 发送异常时不抛异常,仅记录日志
- 现有
MqService.send()调用不受影响,向后兼容 - 项目可正常编译通过
四、风险与依赖
| 风险 | 影响 | 缓解措施 |
|---|---|---|
现有 MqService 被多处使用 |
中 | 不修改 MqService,新建 MqPublisher 接口 |
Message<T> 扩展后序列化兼容性 |
低 | 新增字段均为可空,不影响现有序列化 |
| SpringUtil 在静态方法中可能未初始化 | 低 | MqClient 通过构造器注入,非静态调用 |
五、对标分析
| 维度 | spring-rui (MqDefaultClient) | 本设计 (MqClient) |
|---|---|---|
| 门面类名 | MqDefaultClient |
MqClient(更简洁) |
| Provider 接口 | MqService(含 support/publish) |
MqPublisher(不冲突现有 MqService) |
| 配置类名 | MqAutoConfiguration |
MqProperties(更语义化) |
| JSON 框架 | fastjson2 | Jackson(适配本项目) |
| Provider 支持 | MQTT, RABBITMQ, REDIS | RABBITMQ, REDIS(MQTT 暂不需要) |
| Action 枚举 | Actions(80+ 项) |
MqAction(精简 9 项) |
| 包名 | org.rui.common.mq |
com.rui.common.mq |