这是一篇项目开发指导! 如何设计和开发一个消息管理平台项目

这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战

项目背景

  • 功能: 消息管理平台的主要功能就是给用户发送消息,只要是以官方名义发送的消息,都应该走消息管理平台
  • 消息的类型:
    • IM站内信消息: 应用内聊天的消息
    • PUSH通知栏消息: 系统弹窗消息
    • Email邮件消息
    • SMS短信消息
    • 微信服务号消息
    • 微信小程序消息

项目设计

接口设计

  • 消息管理平台是一个提供消息服务的平台,可以将每种类型的消息写一个接口,将这些接口对外暴露
  • 发送消息的接收人参数定义为数组,如果数组的大小等于1则将文案发送给个人,如果数组的大小大于1, 则将文案批量发送给数组中的所有人
  • 不同的文案发送给不同的人:
    • 提供一个批量接口,可以让调用方一次传入不同文案携带的不同的人
    • 在接口上再封装一层,让调用方能够批量传入

平台功能

  • 平台功能: 调用方调用接口发送短信之后,需要确认短信是否真正到达用户端
    • 发送短信到用户端接收是一个异步的过程:
      • 调用短信提供商的API, 假设入参没有问题,会得到调用成功和失败的提示
      • 要想知道短信是否真正到达用户端,有两种方法:
        • 轮询短信服务商接口,获取最终调用结果
        • 提供一个接口给短信服务商调用,等真正处理完了,短信服务商调用提供的接口,获取最终调用结果

设计优化

  • 接口设计思路:
    • 根据消息类型设计不同的消息发送接口
    • 因为同一个文案可以设计传递给不同的人,所以,人员的传入是一个批量的参数
    • 考虑到有批量调用接口的场景,需要一个批量处理接口
    • 有统计下发消息的场景,所以需要将所有下发的消息抽象出一个消息模板
    • 根据模板设计内容,将消息固化到模板中
  • 消息模板:
    • 消息种类: 消息平台可以发送多种类型的消息,所以模板中需要一个字段来区分不同的消息类型
    • 模板创建者信息: 记录使用者,一般需要记录创建人,更新人的手机号和姓名
    • 消息文案: 消息由内容,标题,图片,链接,视频等内容组成,不同的消息类型,消息内容的组成类型也不一样.可以将消息内容实用json格式存储在一个字段中
    • 消息的业务规则: 对不同类型的消息类型的平台性约束. 这是一个兜底的功能,比如晚上不会收到用户通知栏推送,用户一个小时内不会接收两次推送等
    • 发送账号: 发送的目的账号都抽象为消息管理平台中账号的概念
    • 接收者ID类型: 指定接收者的ID类型,表明这个模板需要传入哪一种类型的ID. 站内IM消息使用的是站内的userId, 通知栏消息使用的是did, 发短信使用的是手机号, 发送微信类消息使用的是openId
    • 运营模板: 运营需要给指定的一批人在指定的时间发送消息.这种属于非实时消息离线推送,不需要技术承接,圈选人群后设置指定的发送时间即可
    • 技术模板: 系统根据业务条件自动触发一批人的消息发送,接收人依赖于业务场景,一般需要实时获取消息
    • 消息内容类型: 区分为通知,营销和验证码.需要将不同消息内容类型的信息通过不同的消息队列发送
  • 总结:
    • 将一条消息相关信息(文案,发送账号,传入的接收者,id类型,消息内容类型),平台信息(业务规则)和基本信息(业务方信息,消息名称)都固化到一个模板中
    • 根据使用场景,区分为运营模板和技术模板.运营模板主要特点是需要填写人群和发送时间,运营模板由消息管理平台自身进行消息调度发送

项目实现

在这里插入图片描述

接口实现

  • 消息管理平台系统架构:

在这里插入图片描述

  • 这些接口统一定义在接入层中,调用者调用消息管理平台的接口方法时,不会直接调用下游的API直接下发消息,因为直接调用下游的API下发消息的风险很大,所以这里的接口只是做简单的参数校验处理和信息补全后将消息发到消息队列上.这样可以保证接口接入层十分的轻量级:

在这里插入图片描述

  • 发送消息队列时,会根据不同的消息类型将消息发送到不同的topic上,发送层只要监听topic进行消费即可:

在这里插入图片描述

  • 发送层消费topic后,会将消息放入各自的内存队列中,多个线程消费内存队列中的消息来实现消息的下发
    • 从接入层发到消息队列时已经做了分topic来实现业务上的隔离,在消费时也是根据放入的各自的内存队列来进行消费,这样就可以实现不同渠道和同渠道的不同类型的消息互不干扰
    • 这里使用内存队列主要原因是为了提高并发度,可以更快地进行消息下发
  • 在下发层实现平台业务规则约束:
    • 夜间屏蔽: 判断是否为夜间,如果勾选了夜间屏蔽那么在夜间的时间点,则对消息进行过滤
    • 一小时去重: 使用userId和消息渠道作为key, 判断消息是否在Redis中,如果存在则过滤掉
    • ID转换: 转换ID, 便于进行数据统计
  • 总结:
    • 支持高并发: 调用方调用接口时,接口不会同步直接调用下游的API发送消息,而是将消息放入消息队列上
    • 业务隔离: 将消息放入消息队列时,可以根据不同渠道以及不同的类型的消息进行分类,放入到不同的topic
    • 提高消费速度: 消费队列时,在本地使用阻塞队列提高消息的消费的并发度

ID转换

  • 因为不同类型的消息需要使用不同的ID类型,比如微信类的openId, 短信的手机号以及通知栏推送的did. 通常情况下,调用者只传入userId, 所以需要根据不同的消息类型对userId进行转换
  • ID转换的实现逻辑:
    • 监听用户变更和微信公众号的订阅和取关的topic,Flink中清洗出一个统一的数据模型,将清洗后的数据写到另一个topic
    • ID映射系统监听Flink清洗出的topic, 实时写到数据源中
  • ID映射采用全量映射:
    • 用户数据通过各种关联关系在Hive中形成一张表
    • ID映射的全量即可根据这张Hive表来实现全量
    • 每天凌晨读取Hive表中的数据,写一遍数据
      • ID映射可以包括一个后台管理,用于手动触发全量,增量和全量的切换,修改全量触发的时间

数据统计

  • 消息管理平台的数据统计都是基于模板的维度实现的:
    • 创建模板时会生成一个模板ID,基于这个模板ID生成一个umpId的值
    • umpId: 15
      • 1位表示消息内容类型,分为技术推送还是运营推送
      • 中间6位是场景ID
      • 8位是时间
  • 所有的消息都会经过接入层,只要消息带有链接,就会给链接脚上umpId参数,链接会一直透传,直到用户完成点击
  • umpId贯穿了所有消息管理平台经过的系统,只要是在消息管理平台发的消息,都会记录下来发送,可以通过点位来快速追踪消息的下发情况

在这里插入图片描述

  • 系统在执行消息的时候都会出现不同的情况导致消息发送不出去,可能是消息去重了,可能是用户的手机号不正确,可能是用户很久未登录,可能是用户屏蔽的相关消息,这时就需要在系统的这些关键位置打上日志,方便排查问题
    • 代表一个个导致错误问题的位置就叫做点位
    • 将点位在关键的位置打上日志就叫做埋点
    • 根据埋点,可以将项目中的点位收集起来,统一处理成需要的数据格式,输出到数据源中
      • 收集日志: 使用LogAgent收集日志到Kafka
      • 清洗日志: 使用Flink实时清洗日志
      • 输出到数据源: 将清洗完的实时日志输出到Redis中,离线保存的输出到Hive
        • Redis中会以多维度对日志数据进行存储来支撑业务需要.这样查询一条消息发送失败的原因,只要使用一个userId即可获取实时关联的信息
        • Hive数据表主要用于离线报表的统计
  • 总结:
    • 设计出业务上的umpId, 为所有推送的消息都加上umpId参数
    • 打通上下游,共同设计和维护关键点位,统一日志格式来实现跨平台的收集和清洗
    • 兼顾实时日志和离线日志需求写入到不同的数据源,实时日志使用多维度统计来快速定位问题

在这里插入图片描述

实现优化

  • 消息管理平台可以对消息需要发送的人群进行圈选,可以支持文件上传和HiveSQL两种方式对人群进行圈选,将圈选出来的人群上传到HDFS中进行读取,支持对人群进行更新,切分,导出的操作
  • 如何避免消息管理平台中消息发送失败的问题:
    • 在圈选新选的特定人群后,使用单独的测试功能测试新选的用户是否能够正常下发消息,文案链接是否存在问题
    • 给用户发送消息,首先需要经过自身的校验,如果确认链接和文案没有问题之后,则提交任务,走工单审批后进行发送
  • 如果启动之后发现文案或者链接存在问题,需要对消息进行拦截,阻止再发送:
    • 针对消息平台的发送功能添加黑白名单功能
    • 线上发送消息添加去重的逻辑: 在某段时间内,过滤掉重复消息,同一个用户需要相隔一段时间才能接收下发的消息

在这里插入图片描述

Supongo que te gusta

Origin juejin.im/post/7065829138078105637
Recomendado
Clasificación