若依消息中心改造:从单一站内信到多渠道集成
📅 2026/7/23 11:05:14
👁️ 阅读次数
📝 编程学习
1. 项目背景与需求分析
若依(RuoYi)作为国内广泛使用的开源后台管理系统,其消息通知模块SysNotice在长期使用中暴露出几个典型问题:首先是功能单一,仅支持站内信形式的简单通知;其次是扩展性差,无法对接多种消息渠道;最后是缺乏统一管理界面,导致消息追踪和统计困难。
在实际企业应用中,消息中心需要承担更复杂的职责:
- 多渠道集成(邮件、短信、企业微信、钉钉等)
- 消息模板管理
- 发送记录审计
- 失败重试机制
- 用户订阅配置
2. 架构设计方案
2.1 核心模块划分
消息中心 ├── 消息网关(Message Gateway) ├── 模板管理(Template Manager) ├── 发送引擎(Delivery Engine) ├── 记录存储(Record Storage) └── 管理界面(Admin Console)2.2 技术选型考量
- Spring Cloud Stream:解决不同消息中间件的适配问题
- Redis Stream:实现消息发送的削峰填谷
- MyBatis-Plus:增强原有ORM层的灵活性
- Vue3 + TypeScript:重构管理前端
关键决策:保留SysNotice表结构但修改用途,仅作为站内信专用存储,避免影响历史数据
3. 核心实现细节
3.1 消息协议标准化
public class UnifiedMessage { private String messageId; // 雪花算法生成 private MessageType type; // 枚举:NOTICE/ALERT/REMINDER private String templateCode; private Map<String, Object> params; private List<Receiver> receivers; private SendConfig config; // 包含重试策略等 }3.2 发送流程优化
- 接收请求时先持久化到MySQL(保证不丢失)
- 通过Redis Stream异步处理
- 采用责任链模式处理不同渠道发送
graph TD A[接收请求] --> B[参数校验] B --> C[持久化记录] C --> D[推送到Redis Stream] D --> E[消费者处理] E --> F{渠道判断} F -->|邮件| G[SMTP发送] F -->|短信| H[对接云厂商API]3.3 失败处理机制
实现要点:
- 自动重试3次(可配置)
- 失败消息进入死信队列
- 提供手动重试接口
- 记录详细错误日志
4. 关键问题解决方案
4.1 性能优化
- 二级缓存设计:
- 本地缓存(Caffeine):存储模板内容
- Redis缓存:存储用户订阅配置
- 批量发送支持:单次API调用支持最多1000个接收人
4.2 权限控制
改造方案:
@PreAuthorize("@ss.hasMsgPerm('send:email')") public Result sendEmailMessage(...) { // 方法实现 }4.3 历史数据迁移
编写Flyway迁移脚本:
-- V2__convert_notice.sql ALTER TABLE sys_notice ADD COLUMN msg_type VARCHAR(20); UPDATE sys_notice SET msg_type = 'LEGACY';5. 前端改造要点
5.1 管理界面增强
- 新增消息看板:展示实时发送统计
- 模板编辑器:支持变量插值语法
- 发送记录查询:支持多条件筛选
5.2 用户端改进
- 消息分类展示(重要/普通)
- 多终端已读状态同步
- 订阅偏好设置
6. 部署注意事项
- Redis配置要求:
spring: redis: stream: poll-timeout: 5000 consumer-group: msg-center-group- Nacos新增配置:
# 邮件发送线程池配置 msg.email.pool.core-size=5 msg.email.pool.max-size=20- 健康检查端点:
@GetMapping("/health") public MessageCenterHealth checkHealth() { // 检查各渠道连接状态 }7. 实测性能对比
测试环境:4C8G服务器,MySQL 8.0,Redis 6.2
| 场景 | 原SysNotice | 新消息中心 | 提升 |
|---|---|---|---|
| 单条发送延迟 | 120ms | 80ms | 33% |
| 批量发送(100条) | 2.1s | 0.8s | 62% |
| 高并发(1000QPS) | 失败率12% | 失败率0.3% | - |
8. 扩展设计建议
- 插件化架构:通过SPI机制支持第三方渠道接入
public interface MessageChannel { String getChannelType(); SendResult send(UnifiedMessage message); }- 流量控制:基于Sentinel实现:
- 按照消息类型限流
- 按照发送方限流
- 消息追踪:集成SkyWalking实现全链路追踪
9. 典型问题排查记录
- 消息重复消费问题
- 现象:相同消息ID被处理多次
- 原因:消费者组配置错误
- 解决:确保每个服务实例有独立consumerGroup
- 模板渲染性能差
- 现象:高并发下模板解析耗时增加
- 优化:引入预编译机制
Template template = TemplateCache.get(templateCode); if(template == null) { template = compileTemplate(templateText); TemplateCache.put(templateCode, template); }- 企业微信回调失败
- 现象:回调URL返回403
- 排查:网关白名单未配置
- 解决:在网关模块添加路径放行规则
改造过程中发现,原有消息表的create_time字段精度只到秒级,建议统一修改为DATETIME(3)存储毫秒时间戳,方便后续问题排查时精确追踪消息流转过程。
编程学习
技术分享
实战经验