什么是消息中心
消息中心是一个集中管理、分发通知和提醒的平台,可以让用户或系统消息更方便、快捷的触达给指定用户或者系统。并且可以帮助用户或系统更好地管理消息的生命周期,屏蔽不同消息渠道差异与技术差异,从而提升效率与体验,降低维护成本。
为什么要搭建消息中心
- 公司目前处于快速发展阶段,业务线正在快速拓展,不同的产品线也正在逐步增加,与此同时,不同的产品线均需要通过消息模块来触达内部或外部用户,基本上每一个系统都需要有自己的消息通知体系。但在由于不同业务开发团队相互独立,为了避免协调沟通这种不可预估的成本,各业务开发团队都采取了“自主”开发的方式解决此类问题。这样造成的结果就是:各业务团队不断地重复发明轮子,而且这轮子不可复用,造成了资源和时间成本的大量浪费。更为关键的是:功能无法复用,持续迭代也无法沉淀。当面对一个新业务时,即便公司已有成熟的功能,但仍然无法有效地缩短业务创新和推进的时间。
- 各业务系统均以功能的概念在设计,业务资源和开发资源会存在大量的重复消耗,在维护方面也存在诸多问题,并且不利于统一管理,并且也没有相关消息触达统计与数据分析能力。
为了适应公司的业务发展以及未来不同场景下的消息应用,我们将引入消息中心概念,抽取通用和稳定的部分划归到消息中心来实现,拆解模块之间的职能,解决重复造轮子,反复改问题的现象。同时将不同的消息渠道整合,为不同的业务线提供不同场景的应用支撑。基于此背景,我们搭建了一个基于内部系统的消息中心。
设计与思考
1 业务系统架构
应用架构这里就不展示了,因为是基于技术部中间件团队java应用(nvwa)工厂生成标准COLA的多模块项目模板应用。
2 消息流程管理
消息通知的流程设计,在各个业务线中通过消息中心提供的接口方法,将不同场景下的消息内容提交到消息中心,消息中心进行统一维护管理,并根据消息的来源和去向,适配相应的推送逻辑:
- 消息生产:涉及到的场景很多,比如活动、系统通知、业务流转、过期提醒等;
- 消息管理:对预发送消息的结构和参数进行校验,并创建消息推送的任务,维护任务级别的推送管理,跟踪消息的状态周期;
- 消息处理:基于消息任务的结构,构建消息推送的主体内容,并对接多个发送渠道,实现通知的高效触达;
- 定时任务:消息可以直接即时推送,但如果是夜间定时任务触发,则要考虑推送延迟问题,将消息放在指定时段投递;
- 渠道对接:通常不同的渠道意味着不同的场景,例如监控推送飞书,邮件走email,业务则应用内通知;
在整个流程中涉及到的模块比较多,状态的流转也很复杂,但是通过消息中心进行统一标准管理和流入流出的跟踪,也可以提供清晰的生命周期监控和维护。大部分的消息通知机制都可以容忍一定的延迟性,所以消息中心完全可以解耦各个流程,引入MQ队列或者异步机制,业务方只需要将请求发送到消息中心,之后由消息中心统一调度和管理即可。
3 数据模型
4 飞书通道与业务系统对接过程中遇到的问题
4.1 老应用有增量消息需接入效率消息中心,效率消息中心该如何解决历史消息转发及复杂交互类型消息的事件回调。
飞书侧机器人回调地址只能填写一个,历史的应用已经对接过飞书平台进行发消息,对于系统增量消息想接入消息中心应该怎么解决,在不影响老系统增量消息接入消息中心的又不影响历史消息回调的情况下,消息中心采用了转发的方式去兼容历史的消息回调。下面是飞书回调流程:
4.2 如何支持飞书通道动态内容消息,消息中心如何去做更友好的兼容适配?
动态消息内容 和 静态消息内容 指的是消息(如邮件、短信、通知等)中的内容。静态消息内容是指在发送消息时事先准备好的、不会发生变化的消息内容,比如营销邮件、欢迎短信、通知公告等。这些内容在每次发送时都是一样的,不会根据接收者的情况、时间等因素而发生变化。而动态消息内容则会根据接收者的情况、时间等因素而实时生成,以提供更好的个性化服务。动态消息内容的例子包括订单确认邮件、账户余额提醒短信、预约成功通知等。这些消息内容需要根据接收者的订单信息、账户信息、预约信息等动态生成。总之,静态消息内容是在发送消息前准备好的、不会发生变化的消息内容,而动态消息内容是根据接收者的情况、时间等因素而实时生成的消息内容,以提供更好的个性化服务。
目前跟业务系统对接的消息内容,99%都属于静态消息内容,相对于那种较复杂的动态消息内容(图一折线图,图二动态表单等动态数据)去做动态数据渲染。消息中心对于动态内容消息渲染,解决方案是在模板功能里面抽象了一层消息内容解析引擎,模板引擎采用的是Apache 软件基金会下的一个开源 Java 模板引擎框架(VelocityEngine)该引擎用于生成 HTML、XML、JSON、CSV 等文件格式的文本内容。功能非常强大,感兴趣的同学可以去了解一下。
下面拿个简单动态消息模板举例:a. API接口组装消息体
{
"reachType": 2,
"templateCode": "*******",
"sendTime": 1687163457335,
"reachList": [
{
"contentParamList": [
{
"key": "addCourseCount", // 动态参数[新增课程总数 (30)]
"value": "30"
},
{
"key": "lastWeekNewCourseCount", // 动态参数[上周上新课程数量 (20)]
"value": "20"
},
{
"key": "dataList", // 动态参数,数据格式用户可自定义
"value": "[{\"courseName\":\"测试课程内容1\",\"courseUrl\":\"https://t1-iwork-rdc.shizhuang-inc.net/rdc/desk\"},{\"courseName\":\"测试课程内容2\",\"courseUrl\":\"https://t1-iwork-rdc.shizhuang-inc.net/rdc/desk\"}] "
}
],
"receiverId": "*******"
}
]
}
b. 使用VelocityEngine语法解析
<code>
#set($myList=$dataList) // api接口传过来的参数
#set($result = '')
#foreach($item in $myList) // 拼接消息内容
#set($result = $result+'['+$item.courseName+']'+'('+$item.courseUrl+')'+'\n')
#end
#set($growthContent="**新人成长(10)**\n$result") // 输出最终消息内容
</code>
c. 动态渲染输出
4.3 在消息中心平台推送大规模消息,如何去跟业务系统的机器人去做平衡而不触发飞书平台限流
业务场景:在一个阳光明媚的早上,业务同学用潮人研习社的机器人给公司用户推送了chatgpt的学习先关的内容,消息推送触达竟然花费了一个1多小时。
问题分析:没办法,做为技术boy,只能埋头去寻找根因,主要有以下几点
- 如上图所示,每次消息推送都要做获取token这个动作,显然获取token这个动作是可以优化的。基于飞书返回的失效时间做近端缓存。
- 消息推送接口虽启用了异步推送,但是在一个消息体里面有很多触达用户时,没有进行分组,底层推送给飞书时还是串行在推消息(这里没有采用飞书的批量发消息接口,是因为在产品侧有个功能要去统计单个用户已读未读的数据,用批量推送的话,具体到用户粒度的已读未读数据飞书是不支持的。另外一个原因就是飞书的机器人不是集中在消息中心进行消息推送,需要考虑飞书侧对某个机器人消息推送做限流的问题,一旦使用了某个业务系统的机器人进行批量或并发推送,可能会导致业务系统业务消息推送(限流)异常)。
优化思路:针对上面2个问题的具体分析,主要是对问题2做了对应的优化,优化思路主要是分治思想,针对大批量推送消息场景对用户进行分组,充分利用操作系统的多核优势。把分组的任务提交到异步消息队列,通过自产自消的方式来提升消息触达效率。
结果:基于上面的思路去优化并测试,效果是异常的明显,之前推送消息需花费1个多小时,现在10分钟(这里的触达时效瓶颈主要是飞书侧,飞书对消息推送接口做了限流(1s并发只能50且1min上限1000))就可以全部触达了。
总结
学会聆听
当完成整个消息中心的设计后,要听取他人意见,学会聆听,因为完成这件事其实并不难。另外在网上也可以找到很多开源产品可借鉴,但是完全拿来主义不一定适合我们自己业务。所以需要跟PM、同事讨论,听取意见。再者消息中心未来是需要长期与其它部门及产品协调沟通的,如果一开始在做的时候就没有与其他人去交流或技术方案讨论,那么后期由于业务拓展,很有可能整体架构很容易被推翻重构。
结语
对于消息中心来说,根据实际业务线的丰富度,相应应用场景也会更加复杂,所以我们在设计消息的落地场景时,对于不同场景的适用性挑战也会增大。但殊途同归,基于降本增效去做更多思考,总归会让价值落地。
作者:Leezr
来源:得物技术
原文:https://mp.weixin.qq.com/s/SWenfaa7obt6XrSA5gZA1A
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。