前言
最新做了一个消息通知服务,涉及到了消息监听,消息封装,消息发送等方面,今天介绍一下我们引用的消息模板处理,供大家参考。
业务场景
- 即时通知(收到消息后立即通知)
- 延时通知(指定时段通知)
流程图
消息服务监听消息队列消息,判断消息是需要实时通知(立即发送),定时通知(在指定时间发送),实时通知则立即调用发送业务进行消息发送(需要根据业务场景的消息量进行具体设计,可以采用批量消费、多线程消费、按照通知的类型拆分成多个topic进行发送及消费,比如短信一个topic、邮件一个topic、推送一个topic等等方式,下面展示定时通知的代码实现)
定时通知
消息实体
1 | java复制代码public class MessageInfo implements Serializable { |
监听消息
1 | typescript复制代码@Component |
监听业务系统发送的消息,根据time是否为空来判断是实时通知还是定时通知,定时通知放入定时通知缓存,实时通知直接发送,调用模板工具及发送实现
定时消息缓存
1 | ini复制代码@Component |
定时消息缓存,使用redis list进行存储,同一分钟的数据会存放在同一个list中,key示例 timing_message:2021-10-01 08:01
定时消息处理
1 | scss复制代码@Component |
前面将定时消息按照前缀+分钟时间作为缓存key,所以定时任务每分钟执行一次,用当前时间生成key去读取缓存,比如指定2021-10-01 08:10发送的消息,定时任务在2021-10-01 08:10就可以从缓存中读取到这些消息并处理掉。
发送实现(伪代码)
发送实现采用接口多实现,指定名称的方式处理,具体可以参考文章
文章链接
1 | typescript复制代码// 接口 |
模板相关(伪代码)
1 | typescript复制代码// 模板管理业务 提供根据模板code获取木板的方法 |
模板的管理可以通过数据库管理或者配置文件,具体实现可以根据自己场景,模板code需要固定下来(约定大于配置),这样在业务系统中根据业务将对应模板code写死即可,在消息通知服务只要不改模板编码,随时调整模板都可以;下面部分介绍模板处理使用的依赖及使用fan
模板处理
通过几个demo演示模板操作的使用方法,供大家参考
示例模板
:尊敬的客户,您购买的xxx商品已发货,预计在xxx时间到达目的地,请您注意查收。
引入ST4
1 | xml复制代码<!-- 项目引入ST依赖 --> |
示例代码
1 | typescript复制代码public static void main(String[] args) { |
ST对于模板变量占位方式比较灵活,但是这一块需要约定好,变量内容得边界使用’{}’还是’<>’都行,变量内容需要是xxx.xxx,因为我们复杂的模板数据可能来自多条不同数据、比如一个物流信息的数据可能来自于用户基础信息和订单信息及物流信息,这多个数据可能有相同的变量名,具体示例入下:
1 | typescript复制代码public static void main(String[] args) { |
总结
一个消息通知服务技术难度并不大,更多的是结合自己的业务场景,业务量来进行设计,在微服务场景下,一个好用且灵活的通知服务能够减轻整个业务系统在消息通知业务上的开发投入,将定时通知的业务处理交给通知服务也是一个可行的方案,结合redis list + 定时任务,技术方案简单,业务灵活性强,业务系统需要给不同用户在不同时间点发送消息,只需要在一个时间点将所有的消息发送到消息系统,比如有100个用户开启了每日通知,且他们通知时间不同,业务系统只需要启动一个每日执行一次的定时任务,一次将所有的通知发送给消息系统,消息系统自行根据通知时间进行通知,这样对于业务系统来说业务更加简单,所有的通知都可以通过一个每日执行一次的定时任务全部发送到消息系统即可,且任务频率降低了,消息通知的压力只需要在消息服务处理即可。
升级空间
- kafka修改为批量消费,参考文章
- topic分区消费,消息服务分布式部署,参考文章
- 拆分不同类型的通知为多个topic,如message-sms message-mail message-push,分别消费处理
- 发送部分升级为多线程处理
本文更多是为了分享技术方案及业务解决思路,在业务细节比较抽象,部分使用伪代码代替,如有不解之处可以评论中提出来
本文转载自: 掘金