当前位置: 欣欣网 > 码农

多平台消息推送服务的实践

2024-03-02码农

架构师(JiaGouX)

我们都是架构师!
架构未来,你来不来?

  • 1 背景

  • 1.1 强耦合的消息和业务代码

  • 1.2 服务间代码重复,维护困难

  • 1.3 消息发送的偶发丢失问题

  • 2 现状和痛点

  • 3 设计和实现

  • 3.1 消息解耦的三元素

  • 3.2 生命周期

  • 3.3 限流

  • 3.4 消息模版

  • 4 总结


  • 1 背景

    随着各项业务线上化,触达用户的方式日益重要,而即时通讯服务成为了至关重要的沟通媒介。诸如企业微信和飞书等消息通知工具已经成为我们与用户互动的首选方式。随着通知需求的不断增加,我们的消息通知代码也在各个服务中逐渐累积,然而,这也伴随着一系列问题的出现。

    1.1 强耦合的消息和业务代码

    消息发送和业务流程代码紧密相连,导致消息发送问题直接影响业务流程。例如,我们的部分流程依赖于用户对发送的消息进行审批,只有审批完成后,才能进入下一流程节点。这种设计使得消息系统的任何故障都可能直接影响整个业务流程的运行。

    1.2 服务间代码重复,维护困难

    不同服务均需消息发送功能,导致多个服务中存在重复的消息发送工具类。这不仅增加了代码的重复性,也使得对消息发送功能的更新和迭代变得复杂。当需要更新消息发送功能时,必须在各个服务中分别进行修改,增加了维护的难度和出错的可能性。

    1.3 消息发送的偶发丢失问题

    目前的架构中,大量消息通过多个服务的工具类直接调用各消息平台的HTTPS接口发送。这种设计在生产环境中导致了消息偶发性的丢失——消息虽然发送,但用户未收到。由于代码分散,排查此类问题非常困难,我们只能依赖于发送时的日志进行追踪,这大大增加了问题诊断的复杂性。


    2 现状和痛点

    在我们实际业务中,多个服务常常需要向用户发送不同形式的消息,包括但不限于企业微信、飞书、短信、邮件、微信通知和手机应用通知等。如果每个服务都独立开发一套消息发送代码,这将导致维护难度大、错误率高,效率极低。为解决这一问题,我们开发了「信鸽平台」,这是一个集中式的消息服务平台,为其他服务提供统一的消息发送解决方案。与公司内的其他中台服务类似,信鸽服务的主要目标是实现业务消息的优雅传递。该服务专注于消息的全周期管理,确保消息发送的稳定性,并提供业务分析功能,以更高效、可靠的方式处理各种业务通知需求。

    3 设计和实现

    为了让信鸽服务的接口能被使用的更方便,信鸽服务内部需要完成多个步骤

  • 消息服务接口鉴权

  • 模版加载处理

  • 消息前置校验

  • 多消息通道频控兼容

  • 消息重试处理

  • 消息生命周期监控

  • 3.1 消息解耦的三元素

    结合实际的业务场景,我们把消息拆分出了三个元素:场景、机器人、模版

  • 场景:当前发送的消息的业务场景

  • 机器人:发送当前的机器人/应用

  • 模版:当前消息模版

  • 通过以上三元素的简单配置,来达到我们信鸽消息对象的完整配置

    3.2 生命周期

    不同平台的消息,在信鸽中都拥有着统一生命周期:

  • 初始化

  • 发送中

  • 消息发送成功

  • 消息重试中

  • 消息发送失败

  • 在实际生产环境中,若由于某种因素需要查看消息的状态,可根据消息唯一号,判断消息的状态。

    3.3 限流

    3.31 对外部平台频控策略的适配

    当我们的消息发送频率超出各平台的限制时,会导致消息发送失败并被丢弃。这对于那些依赖于消息传达的关键场景来说,可能造成严重的影响。此外,先前提及的消息偶发丢失问题,大多也是由于这些外部平台的频率控制导致的。

    飞书限流规则:

  • 所有接口每个应用最高请求频率 50次/秒

  • 发送消息接口每个应用最高频率是1000次/分钟

  • 群聊机器人Webhook最高频率是100次/分钟

  • 机器人给同一用户或同一群发的最高频率是5次/秒

  • 企微限流规则:

  • 每个机器人发送的消息不能超过20条/分钟

  • 对每个机器人/应用作对外适配的频率限制:

    因此,信鸽平台采用了简易的分布式限流算法,并结合模板方法和策略模式,实现了两种限流机制:计数器算法和令牌桶算法。通过自定义注解,我们可以在项目中灵活地切换限流配置,从而有效适应不同平台的频率控制策略。这样的设计不仅提高了系统的适应性,也确保了消息传递的稳定性和效率。

    限流后带来的堆积排队问题

    在企业微信应用中设定了每分钟最多向每个用户发送30条消息的限制。假设在某一时刻,场景A产生了210条消息,那么按照这个发送频率,至少需要7分钟才能完成所有消息的发送。此外,如果在这个过程中,场景B产生了一条消息,这条消息将不得不等待场景A的所有消息发送完毕后才能被发送。这样的处理机制可能导致消息传递的延迟,特别是在高峰时段或多场景并发时。

    所以我们进行了改造:基于场景分区,消费者会根据分区轮询消费。而不是等待A队列消费完成后再消费B队列。这样有效降低了同一机器人下的限流堆积问题。当然,如果有更大体量的消息,还是建议使用多个机器人来提高消费的速率。

    3.32 信鸽接口的限流

    考虑到服务是通过SCF层进行接入的,我们可以利用SCF提供的配置来实现接口限流。这意味着,通过简单地配置SCF接口,我们就能轻松实现上线接口的限流功能。这种方法简化了限流的实现过程,确保服务在高并发情况下的稳定运行,同时降低了系统复杂性和维护成本

    3.4 消息模版

    为了方便各服务快速发送基本消息,信鸽平台提供了一套消息模板。这些模板旨在简化消息发送流程,用户只需填充必要的参数并进行接口调用,即可轻松发送一条消息。这种设计极大地提高了消息发送的效率,同时降低了服务集成的复杂性。下面提供的是一个用于飞书消息发送的模板示例,展示了如何便捷地使用这些模板发送消息。


    4 总结

    本文概述了信鸽服务,它已经成为新媒体业务体系中的核心组件,承担着消息发送的统一服务职责。信鸽服务的核心目标是实现消息的集中管理和高效传递。展望未来,我们计划进一步增强信鸽服务的功能,包括事务消息处理、消息的优先级排序,以及夜间消息发送的屏蔽控制。这些改进将使信鸽服务更加全面和强大,更好地服务于业务需求。

    如喜欢本文,请点击右上角,把文章分享到朋友圈
    如有想了解学习的技术点,请留言给若飞安排分享

    因公众号更改推送规则,请点「在看」并加「星标」 第一时间获取精彩技术分享

    ·END·

    相关阅读:

    作者:吴冰寒

    来源:转转技术

    版权申明:内容来源网络,仅供学习研究,版权归原创者所有。如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!

    架构师

    我们都是架构师!

    关注 架构师(JiaGouX),添加「星标」

    获取每天技术干货,一起成为牛逼架构师

    技术群请 加若飞: 1321113940 进架构师群

    投稿、合作、版权等邮箱: [email protected]