统一消息分发中心设计

背景

我们核心业务中订单完成时,需要完成后续的连带业务,扣件库存库存、增加积分、通知商家等。

如下图的架构:

这样设计出来导致我们的核心业务和其他业务耦合,每次新增连带业务或者去掉连带业务都需要修改核心业务。

一方面,不合符软件设计的OCP原则;

二方面,修改核心业务风险、成本也是很大的。

方案

基于上述方案的问题,我们设计了新的方案。新的方案,可以动态接入新的连带业务,不会入侵核心业务,降低了变动的风险和成本。

1. 订单下发统一的ORDER_CREATED事件消息;

消息格式如下:

{

"enterEvent":"ORDER_CREATED",

"data":{

"order_id":"OR2023111000000001"

},

"source":"ORDER",

"datetime":"2023-11-10 21:40:52"

}

2. 所有核心业务发送到MQ的消息,统一发送到分发中心 DISPATCHER_CENTER。

消息统一中心获取配置的路由信息,将消息发送到MQ。

java 复制代码
**
 * @author darmi
 */
@Component
public class KafkaEventListener {

  @Autowired
  private MsgDispatcherCenterRepository msgDispatcherCenterRepository;

  @Autowired
  private KafkaTemplate<String, String> kafkaTemplate;

  @Autowired
  @Qualifier(value = "eventExecutor")
  private Executor eventExecutor;


  @KafkaListener(topics = {"DISPATCHER_CENTER"})
  public void dispatchMsg(String event) {
    DispatcherCenterEvent dispatcherCenterEvent = DispatcherCenterEvent.getObject(event);
    eventExecutor.execute(() ->{
      msgDispatcherCenterRepository.findMsgDispatcherCenterByCenterEventAndActive(
          dispatcherCenterEvent.getCenterEvent(), Boolean.TRUE)
          .forEach(e -> kafkaTemplate.send(e.getRouteEvent(), dispatcherCenterEvent.getData()));
    });
  }

}

Mysql的消息路由表设计如下:

sql 复制代码
CREATE TABLE `tb_msg_dispatcher_ center` (
  `id` int NOT NULL AUTO_INCREMENT,
  `center_event` varchar(255) NOT NULL,
  `route_event` varchar(255) NOT NULL,
  `active` tinyint NOT NULL DEFAULT '0',
  `created` timestamp NOT NULL,
  `updated` timestamp NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_center_event_active` (`center_event`,`active`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

3. 各个业务监听消息,处理自己的业务。

java 复制代码
 @KafkaListener(topics = {"ADD_POINT"})
  public void addPoint(String event) {
  //    添加积分
  }

  @KafkaListener(topics = {"REDUCE_STOCK"})
  public void reduceStock(String event) {
    //   扣件库存
  }

  @KafkaListener(topics = {"NOTICE_MERCHANT"})
  public void noticeMerchant(String event) {
    //    通知商家
  }

总结

这个方案是一个简易可行的方案,符合快速上手并实施。在人力、时间、成本不充足的情况下,基本能满足我们的需求。

如果想让它作为平台级的技术组件推广,还有一些细节的点可以优化。

  • 核心的业务也可以分离出来,通过平台配置的方式自动分发数据到消息中心。
  • 消息中心每次都会从数据库拉去路由表信息,性能不好,可以放在分布式缓存或本地内存。这时需要注意缓存数据的一致性问题。
  • 分发中心是否存在性能瓶颈、集群化等。
  • 连带业务是否也可以通过配置,自动拉取MQ的消息。
相关推荐
用户83071968408213 小时前
Java 告别繁琐数据统计代码!MySQL 8 窗口函数真香
java·sql·mysql
带刺的坐椅14 小时前
SolonCode v0.0.20 发布 - 编程智能体(新增子代理和浏览器能力)
java·ai·agent·solon·solon-ai·claude-code·openclaw
stark张宇15 小时前
MySQL 核心内幕:从索引原理、字段选型到日志机制与外键约束,一篇打通数据库任督二脉
数据库·mysql·架构
倔强的石头_15 小时前
融合数据库架构实践:关系型、JSON与全文检索的“一库多能”深度解析
数据库
会员源码网15 小时前
数字格式化陷阱:如何优雅处理 NumberFormatException
java
孔明click3316 小时前
Sa-Token v1.45.0 发布 🚀,正式支持 Spring Boot 4、新增 Jackson3/Snack4 插件适配
java·sa-token·开源·springboot·登录·权限认证
程序猿阿越16 小时前
Kafka4源码(二)创建Topic
java·后端·源码阅读
悟空码字16 小时前
Spring Boot 整合 MongoDB 最佳实践:CRUD、分页、事务、索引全覆盖
java·spring boot·后端
省长16 小时前
Sa-Token v1.45.0 发布 🚀,正式支持 Spring Boot 4、新增 Jackson3/Snack4 插件适配
java·后端·开源
NE_STOP17 小时前
MyBatis-动态sql与高级映射
java