聊聊 消息推送的架构设计

点击关注公众号:互联网架构师,后台回复 2T获取2TB学习资源!

上一篇:2T架构师学习资料干货分享

架构目标

构建企业级统一基础推送服务,支持通过多渠道推送,能够统一集成的电子邮件、短信、聊天、钉钉、企业微信和其他公共社交应用:

  • 聊天 - 微信Wechat/QQ

  • 站内推送通知(移动设备和Web浏览器)

  • 站外推送通知(移动设备,APP没有开启)

  • 短信(如登录密码、营销活动)

  • 电子邮件

  • 钉钉

  • 企业微信

企业级统一基础推送服务,是一个通用特性,适用于所有现代分布式应用,无论采用何种编程语言和技术。

推送能力的演进

第一阶段(模块化):各自为政、各自封装

企业内部,早期业务量比较少,各系统基本都是有自己的推送模块,类型也是五花八门:

  • 聊天模块

  • 短信模块

  • 电子邮件模块

  • websocket 模块

各自封装模块比较简单,但是实现分散、各系统模块的质量也很难统一保证。

第二阶段(框架化):集成框架

为了减少重复性设计、开发成本, 设计了统一的推送框架

同一套微服务框架,共用一个统一的推送框架

为了解决上述分散实现的问题,企业内部统一实现了一个综合各类推送功能的基础库,供业务方统一调用。

  • 聊天基础starter

  • 短信基础starter

  • 电子邮件基础starter

  • websocket 基础starter

于是,我们把 springboot-starter的逻辑封装到了服务治理框架内,微服务服务启动时,每一个服务对各种的starter进行运维管理、配置管理。

第三阶段(服务化):推送服务

集成到框架,每一套服务,都需要重复性的解决3高问题。

  • 推送服务,数据量大,需要解决跨库查询问题

  • 推送服务,性能要求高,需要解决高并发问题

大数据量、并发量高,意味着:

  • 硬件资源投入大

  • 运维成本高

这样的基础服务,需要进行沉淀,剥离,集中成统一的、基础服务,由专门团队负责维护、迭代、运维。降低重复投入、重复建设成本, 真正的降本增效。

于是, 推送框架 演进为 推送服务

推送服务在业务系统中的位置

一个业务应用, 基本上有很多原子服务编排、整合而来,最终构建出一个完整的架构图。

  • 接入层,这是外部请求进入内部系统的门户,所有的请求都必须通过 API 网关。

  • 应用层,也被称为聚合层,它为相关业务提供聚合接口,并调用中台服务进行组合。

  • 原子服务,包括就是原子技术服务,原子业务服务,根据业务需求提供相关的接口。原子服务为整个架构提供可复用的能力。

例如,在B站视频网站平台上,评论服务作为一项原子服务,在B站的视频、文章、社区都需要,那么为了提高复用性,评论服务就可以独立为原子服务,不能与特定需求紧密耦合。

在这种情况下,  评论服务,需要供一种可以适应不同场景的复用能力。

84e703b364a303a4d3d3551ad3a1e5b0.png

类似的,文件存储、数据存储、推送服务、身份验证服务等功能,都会沉淀为原子服务,业务开发人员,在原子服务基础上,进行编排、配置、组合,可以快速构建业务应用。

推送服务功能要求

  • 发送通知

  • 对通知进行优先级排序

  • 根据客户的保存偏好发送通知

  • 支持单个/简单的通知消息和批量通知消息

  • 各种通知的分析用例

  • 通知消息的报告

推送非功能性需求(NFR)

  • 高性能:qps > 1W

  • 高可用性(HA):99.99%

  • 低延迟:TP99 在10ms以下

  • 高扩展:可扩展/可插拔的设计,以便添加更多适配器和提供商,与所有通知模块的API集成以及与客户端和服务提供商/供应商的外部集成

  • 跨平台:支持Android/iOS移动设备和桌面/笔记本电脑的Web浏览器

  • 自伸缩:可在本地(VMware Tanzu)和 AWS、GCP 或 Azure 等公共云服务上扩展负载

推送系统设计架构

1f06271d004955d1216d96b7190b960c.png

这些解决方案设计的考虑因素和组件包括:

1. 通知客户端

这些客户端通过 API 调用请求单个和批量消息。它们将向简单和批量通知服务发送通知消息。

  • 简单通知客户端:专门用于发送单个通知的客户端,负责向用户发送单一通知。这些客户端通常用于向特定用户发送重要通知,例如密码找回或账户异常提醒。

  • 批量通知客户端:专门用于发送批量通知的客户端,负责向用户批量推送通知。这些客户端通常用于需要通知大量用户的场景,例如企业内部通知或营销活动。

2. 通知服务

作为入口点的这些服务,通过暴露 REST API 与客户端互动。

它们负责构建通知消息,通过调用"模板服务"。这些消息将使用"验证服务"进行验证。

  • 简单通知服务:该服务将提供 API,主要负责处理简单通知请求,提供与后端服务集成的 API,以便将通知发送给用户。这种服务通常用于处理较少的通知请求,例如针对特定用户或事件的简单通知。

  • 批量通知服务:该服务将提供 API,主要负责处理批量通知请求,提供与后端服务集成的 API,以便批量发送通知。这种服务通常用于处理大量的通知请求,例如企业内部的批量通知或营销活动的批量推送。

此服务还将管理通知消息。它将发送的消息持久化到数据库并维护活动日志。

可以使用这些服务的 API 重新发送同一条消息。

它将提供添加/更新/删除和查看旧消息和新消息的 API。

它还将提供 Web 仪表板,该仪表板应具有筛选选项,以根据不同的条件(如日期范围、优先级、模块用户、用户组等)筛选消息。

3. 模板服务

此服务主要负责所有可用的一次性密码(OTP)、短信、电子邮件、聊天以及其他推送通知消息的模板管理。

它还提供了 REST API,以便创建、更新、删除和管理模板。

除此之外,它还将提供一个用户界面(UI)的仪表板页面,使用户能从网络控制台检查和管理各种消息模板。

4. 消息分发服务

  • 定时分发服务:

该服务将提供API来安排立即或指定时间的通知。可以是以下任何一种:

  • 分钟

  • 每小时

  • 每天

  • 每周

  • 每月

  • 每年

  • 自定义频率等。

还可能有其他自动触发的服务,基于预定时间进行消息触发。

  • 消息验证服务:

此服务全权负责根据业务规定和预期格式对通知信息进行核实。批量通知需由授权的系统管理员同意。

  • 消息优先级服务:

该服务负责对通知进行优先级排序,分为高、中、低三个等级。

通知信息具有较高的优先级和有时间限制的到期时间,它们将始终以较高优先级发送。

"通用出口处理器"会接收消息并根据相同的优先级从高、中和低三个不同的队列中发送和处理。

在非工作时间,可以以低优先级发送批量通知。

在交易过程中的应用程序通知可以发送到中优先级,如电子邮件等。企业可以根据通知的重要性确定优先级。

5. 事件优先级队列(消息队列)

此服务提供事件中心功能,负责接收通知服务的高、中、低三个优先级的信息。

它会根据业务的优先级来发送和接收通知。企业可以根据通知的重要性来设定优先级。

服务内部包含三个主题,用于根据业务优先级接收和发送通知:

  • 低优先级:主要用于在非工作时间发送批量通知。

  • 中优先级:适用于在交易过程中发送的应用程序通知,如电子邮件等。

  • 高优先级:通知信息具有较高的优先级和有时间限制的到期时间,它们将始终以较高优先级发送。

6. 通用出站处理程序

该服务通过轮询事件优先级队列来接收事件中心中的通知信息,并根据其优先级进行处理。

高优先级的通知会优先处理"高"队列,依次类推。

最后,它通过事件中心将通知信息发送到特定的适配器。

此外,该服务还从用户选择服务中获取目标用户/应用程序,以便进行通知的分发。

在处理过程中,通用出口处理器会根据事件的优先级进行相应的操作,确保重要事件得到优先处理。

这样,企业可以根据通知的优先级来确定处理顺序,从而提高通知的处理效率。

除此之外, 通用出站处理程序,还能进行消息的进一步按照通道类型进行分发:

该服务将消息发送到各种支持的适配器。

这些适配器会根据不同的设备(如桌面/移动设备)和通知类型(如短信/OTP/电子邮件/聊天/推送通知)进行转换。

7. 通知适配器

这些转换器将从消息队列(rocketmq)接收传入信息并根据其所支持的格式传递给外部合作伙伴。

以下是一些转换器,根据需求可以增加更多:

  • QQ 通知适配器服务

  • 微信Wechat 聊天通知适配器服务

  • 应用内通知适配器服务

  • 电子邮件适配器服务

  • 短信适配器服务

  • OTP 适配器服务

8. 通道供应商

这些是外部的 SAAS(云上/本地)服务提供商,利用它们的基础设施和技术实现实际的通知传递。

它们可能是像 AWS SNS、MailChimp 等的付费推送通道服务。

  • QQ 供应商集成服务

  • 微信Wechat 供应商集成服务

  • 应用推送通知供应商集成服务

  • 电子邮件供应商集成服务

  • 短信供应商集成服务

9. 用户选择服务

该服务提供选择目标用户和各种应用程序模块的功能。

这可能包括将批量消息发送到特定的用户组或不同的应用程序模块。

可能是 AD/IAM/eDirectory/用户数据库/用户组,具体取决于客户的偏好。

在服务内部,它将使用"用户配置文件服务"API 来消费和检查客户的通知偏好。

10. 用户配置文件服务

此服务提供各种功能,包括管理用户配置文件及其偏好设置。

还管理内部用户标识,和外部通道标识之间的关联关系

  • 钉钉用户标识 和 用户标识 关联关系

  • 企业微信 用户标识 和 用户标识 关联关系

  • 用户和邮箱的关联关系

  • 等等

它还将提供取消订阅通知以及通知接收频率等功能。

"通知服务"将依赖于此服务,以便根据用户的通知偏好来发送通知。

此外,该服务还可以用于统计和分析用户对通知的偏好,以帮助企业优化通知策略。

11. 分析服务

该处理器将负责执行所有的分析工作,识别通知使用情况、趋势并生成报告。

它将从分析数据库(Cassandra)和通知数据库中提取所有最终的通知信息,用于分析和报告目的。

以下是一些用例:

  • 每天/每秒的总通知数

  • 哪个通知系统使用最频繁

  • 消息的平均大小和频率

  • 基于优先级过滤消息等等...

12. 通知跟踪器

此服务将持续监视事件中心队列并跟踪所有发送的通知。

它捕获通知的元数据,如传输时间、传送状态、通信渠道、消息类型等。

13. 通知数据库:Mysql数据库集群

通知数据库,用于存储库用于存储所有通知信息,包括发送时间、状态等。

它包括一个数据库集群,其中领导者用于执行所有写操作,读取操作则在读取副本/跟随者上进行。

这个数据库群集将持久化所有通知,供分析和报告使用。

它基于“写入更多,读取更少”的理念。

它能提供良好的性能和低延迟,适应大量的通知,因为它内部处理大量的写操作,并与其他数据库节点同步,保持高可用性和可靠性的冗余数据/消息。

在任何节点崩溃的情况下,消息将始终可用。

作者:Mark、尼恩

来源:技术自由圈

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

正文结束

推荐阅读 ↓↓↓

1.JetBrains 如何看待自己的软件在中国被频繁破解?

2.无意中发现了一位清华妹子的资料库!

3.程序员一般可以从什么平台接私活?

4.40岁,刚被裁,想说点啥。

5.为什么国内 996 干不过国外的 955呢?

6.中国的铁路订票系统在世界上属于什么水平?                        

7.15张图看懂瞎忙和高效的区别!

2c5381b3cf0223ba279ead44c63d51a7.gif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【资源介绍】 Java基于Netty实现的高性能分布式IM即时通信系统源码+项目说明.tar 介绍 `RIM`是基于Netty实现的面相开发者的高性能分布式即时通信系统,保证消息的实时性、有序性、可靠性。 ## 技术栈 | 名称 | 作用 | | -------------- | ------------------------------------------------------------ | | SpringBoot | 利用IOC特性简化开发 | | Mybaits-plus | 简化与mysql的交互过程 | | Netty | 高性能消息收发、心跳检测、应用层ACK | | Redis | 保存用户会话信息、去重信息、群聊单聊的离线消息以及其他信息的缓存 | | Mysql | 持久化信息 | | RabbitMQ | 将存储操作异步,利用RabbitMQ的可靠性机制返回ACK | | Zookeeper | 注册中心、感知服务节点变化情况 | | Dubbo | 在路由层利用泛化调用实现定向功能调用,以及服务之间方法调用 | | Kryo | 序列化协议 | | Leaf-SnowFlake | 利用美团改进的雪花算法生成局部有序的消息id | ## 模块结构 | 模块 | 作用 | | ---------------- | ------------------------------------------------------------ | | rim-client | 客户端:负责接入IM系统、应用层ACK | | rim-router | 路由层:负责消息(群聊、单聊、离线)转发、用户回话信息管理、应用层ACK | | rim-server | 服务层:消息 | | rim-store | 存储层:消息(群聊、私聊)持久化、离线消息查询、应用层ACK | | rim-id-generator | ID生成层:生成群聊、单聊的消息id | ## 亮点 + 设计模式 + 使用策略模式实现Client的各种内置命令、Netty接收消息处理、Router转发逻辑等功能 + 使用读扩散实现群聊离线消息拉取 + 使用RabbitMQ的可靠性机制为客户端返回ACK、异步执行消息持久化 + 使用Dubbo的泛化调用机制实现服务的定向调用,解决了因分布式IM_Server的部署导致的用户信息分散在不同服务器上的问题 + Dubbo泛化调用的地址为一致性哈希负载均衡算法计算所得 + 解决了自定义协议在传输中导致的粘包、拆包问题 + 群聊批量ACK处理,避免因创建过多的超时计时器导致的压力过大 + 利用leaf-sno 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,也适用于小白学习入门进阶。当然也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或者热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载,沟通交流,互相学习,共同进步!
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于springcloud+Netty+MQ+mysql的分布式即时聊天系统源码+数据库+项目说明.zip # KT-Chat 分布式即时聊天系统 **技术选型**:Java、SpringCloud、Nacos、Sentinel、Netty、MySQL、Redis、RocketMQ 等 **项目描述**:项目基于 SpringCloud Gateway + Nacos + Sentinel + OpenFeign 作为分布式系统架构,基于 Netty 实现高性能网络通信。主要功能有:一对一聊天以及群组聊天、好友管理、群组管理等。 项目独立完成,包括需求分析、设计、开发实现。 关于我在项目中使用 MySQL 读写分离的总结:[MySQL主从延迟的解决方案](https://blog.csdn.net/KIMTOU/article/details/125033199) ## 用例分析 用户能够在聊天系统上进行网络通信,与好友进行实时一对一聊天,与群组成员进行群聊。用户用例图如下所示: 1. 用户登录:登录系统 2. 聊天:包含与好友进行一对一聊天,与群组成员进行群聊。 3. 群聊管理:新建群聊、加入群聊、退出群聊。 4. 好友管理:显示好友列表,添加、删除好友。 5. 在线离线状态显示:查看好友的在线、离线状态。 6. 聊天记录管理:将聊天记录存入数据库,能够显示、删除存储的聊天记录。 <img src="https://cdn.tojintao.cn/Chat原理图.png" alt="img" style="zoom:67%;" /> ## 系统设计 #### 系统总体设计 分布式即时聊天系统分为用户信息子系统、长连接管理子系统、聊天信息子系统共三个子系统,API 网关负责将请求路由至各个子系统。 * 用户信息子系统包含权限校验模块、用户登录模块、好友管理模块,其中好友管理模块包括好友列表、添加好友、删除好友功能; * 长连接管理子系统包含在线状态管理模块、聊天主模块、消息模块,其中聊天主模块包括一对一聊天和群聊功能; * 聊天信息子系统包含群聊管理模块、聊天记录管理模块,其中群聊管理模块包括新建群聊、加入群聊、退出群聊功能。 <img src="https://cdn.tojintao.cn/KT-Chat系统结构图.png" style="zoom:67%;" /> #### 系统架构设计 ![](https://cdn.tojintao.cn/KT-Chat系统架构设计.png) 项目基于 Nacos 作为注册中心,将各个服务注册进 Nacos,包括 Netty 服务端;使用 SpringCloud Gateway 作为服务网关,是所有请求的统一入口;限流组件使用 Sentinel;基于 Netty 进行通信、维护长连接;RocketMQ 作为消息队列,处理聊天消息的异步入库以及解决分布式 Netty 节点问题; Zookeeper 用于分布式 id 的生成;Redis 用于记录用户在线状态以及记录 Netty 节点的元数据;MySQL 对数据进行持久化。 ## 运行截图 #### 一对一聊天 ![](https://cdn.tojintao.cn/聊天测试1.PNG) #### 群聊 ![](https://cdn.tojintao.cn/群聊测试1.PNG) ## 启动说明 1. 启动本项目时,需提前启动 Nacos、RocketMQ、MySQL、Redis、ElasticSearch、Sentinal 实例。 2. conntector 与 connector-2 这两个模块并不一样,connector-2 使用了 Dubbo 进行消息转发(实验阶段),而 connector 使用 Feign 进行 HTTP 调用转发消息。启动 connector 就行了。 3. 每个服务都允许运行多个实例。
当然可以!使用 Python 和钉钉机器人 API,你可以编写以下代码实现将用户发给钉钉单聊机器人的消息给某个人或某个钉钉群聊: ```python import requests import json def send_dingtalk_message(webhook, message): headers = {'Content-Type': 'application/json;charset=utf-8'} data = { "msgtype": "text", "text": { "content": message } } response = requests.post(webhook, data=json.dumps(data), headers=headers) result = response.json() if result["errcode"] == 0: print("消息成功!") else: print("消息失败:", result["errmsg"]) # 钉钉机器人的 webhook 地址 webhook = "https://oapi.dingtalk.com/robot/send?access_token=your_access_token" # 用户发给钉钉机器人的消息 user_message = "用户发来的消息" # 要的钉钉群聊的 webhook 地址 group_webhook = "https://oapi.dingtalk.com/robot/send?access_token=your_group_access_token" # 用户消息给某个人 send_dingtalk_message(webhook, user_message) # 用户消息给某个群聊 send_dingtalk_message(group_webhook, user_message) ``` 请注意,你需要将 `your_access_token` 替换为你的钉钉机器人的 access_token,以及将 `your_group_access_token` 替换为你要的钉钉群聊的 access_token。 这段代码通过发 HTTP POST 请求到钉钉机器人的 webhook 地址,将用户发来的消息以文本形式给指定人或群聊。如果发成功,会打印出“消息成功!”;如果发失败,会打印出具体的错误信息。 希望对你有所帮助!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值