1.背景
1.1 现状
随着业务的快速变化,涉及消息发送的场景越来越多。当前各业务线重复搭建消息能力,引发了开发耗时长,维护困难,消息无法追溯等一系列问题。这样,我们就需要一个统一的消息中心来解决这些问题。消息发送是很多业务系统都会用到的一个基础能力,当前在整个消息发送流程在各个环节都存在着大大小小的一些问题,如下图所示,这些都极大地增加了我们的日常开发以及维护成本。
1.2 需求分析
2.技术方案设计
2.1 架构设计
2.2 主要流程
2.3 实体模型设计
2.4 使用方调用链路
3.技术难点
3.1 消息通道设计
采用模版方法设计模式,将每个通道的唯一识别码作为通道容器唯一标识,应用初始化时,则将通道实例初始化到容器中,发送消息时根据消息对应的通道实现具体的消息发送逻辑。
3.2 消息状态追踪
消息状态追踪,是获取消息的投递状态以及读信状态的一种能力,开发可以快速追溯消息发送过程中的一些问题。这里有两种技术方案:
- 后台起一个定时任务,以一定的频率去查询还未查询到状态的消息,然后去调用消息服务提供方查询接口查询投递状态,如果状态查询成功,则更新消息状态。如果查询失败或者消息还在投递中,则在下次定时任务里再次查询,失败累积到一定次数时,则不再查询。
- 在消息投递之后,发送一个延迟RocketMQ消息(RocketMQ自带延迟消费的能力),consumer接收到RocketMQ消息后,去消息服务提供方查询状态,如果状态查询成功,则更新消息状态。如果查询失败或者消息还在投递中,则利用RocketMQ的重传机制去重试。
两种方案都能实现异步消息状态查询的能力,但是使用第一个方案,会面临几个问题,
- 定时任务的执行间隔不好设定,时间间隔太短可能会导致部分消息还在投递中,不能查到消息状态,时间间隔太长又会导致从消息状态查询延迟太大,而使用RocketMQ的延迟消费能力则能很好地解决这个问题,所有消息投递之后一段时间(比如10秒)去查询,那么绝大多数消息10秒就能查询到状态。
- 状态查询失败了,下次定时任务会去重试,失败的数据多了,还会产生消息堆积,RocketMQ的失败重试机制也能很好地解决这个问题。
- 重试策略上,定时任务是以恒定的频率去重试,会存在IO资源的浪费,而RocketMQ的重试使用了指数退避的思想,每次以更大的时间间隔去消费,这样可以让IO资源得到合理的利用。
综上所述,消息中心使用了第二种方案去做消息状态追踪。
4.小结
本篇是笔者在实际业务开发中遇到的关于消息中心的技术解决方案,包括了架构设计,主要功能流程,还有一些实现的技术原理与难点。