CHAPTER 10: 《DESIGN A NOTIFICATION SYSTEM》第10章 《设计一个通知系统》

通知系统已经成为许多应用进程非常流行的功能近年来。通知提醒用户重要信息,例如突发新闻、
产品更新、活动、产品等。它已成为我们日常生活中不可或缺的一部分。在本章中,您将被要求设计一个通知系统。

通知不仅仅是移动推送通知。三种类型的通知格式
分别是:移动推送通知、短信和电子邮件。图 10-1 显示了一个示例这些通知中的每一个。
在这里插入图片描述

第 1 步 - 了解问题并确定设计范围

构建一个每天发送数百万条通知的可扩展系统并非易事。它需要对通知生态系统有深入的了解。面试问题是故意设计为开放式和模棱两可的,您有责任询问问题以阐明要求。

应聘者:系统支持哪些类型的通知?
面试官:推送通知、短信和电子邮件。
应聘者:是实时系统吗?
面试官:让我们说这是一个软实时系统。我们希望用户接收通知尽快。但是,如果系统处于高工作负载下,则会有轻微的延迟可以接受。
应聘者:支持哪些设备?
面试官:iOS 设备、Android 设备和笔记本电脑/台式机。
应聘者:什幺会触发通知?
面试官:通知可以由客户端应用进程触发。它们也可以是在服务器端调度。
应聘者:用户可以选择退出吗?
面试官:是的,选择退出的用户将不再收到通知。
应聘者:每天发送多少条通知?
面试官:1000 万条移动推送通知、100 万条短信和 500 万条电子邮件。

第 2 步 - 提出高级设计并获得支持

本部分介绍支持各种通知类型的高级设计: iOS 推送通知、Android 推送通知、短信和电子邮件。其结构如下:

  • 不同类型的通知
  • 联系信息收集流程
  • 通知发送/接收流程
    不同类型的通知
    我们首先了解每种通知类型在较高层次上的工作方式。
    iOS 推送通知
    在这里插入图片描述
    我们主要需要三个组件来发送 iOS 推送通知:
  • 供应商。提供进程生成通知请求并将其发送到 Apple 推送通知服务 (APNS)。若要构造推送通知,提供进程提供以下功能数据:
  • 设备令牌:这是用于发送推送通知的唯一标识符。
  • 有效负载:这是一个包含通知有效负载的 JSON 字典。这是一个
    例:
    在这里插入图片描述
  • APNS:这是 Apple 提供的一项远程服务,用于将推送通知传播到 iOS设备。
  • iOS 设备:它是接收推送通知的终端客户端。

Android 推送通知
Android 采用类似的通知流程。Firebase Cloud Messaging 不使用 APNs,而是使用 APNs(FCM) 通常用于向 Android 设备发送推送通知。
在这里插入图片描述
短信
对于 SMS 消息,第三方 SMS 服务,如 Twilio [1]、Nexmo [2] 等常用。其中大多数是商业服务。
在这里插入图片描述
电子邮件
尽管公司可以创建自己的电子邮件服务器,但其中许多公司选择商业电子邮件服务。Sendgrid [3] 和 Mailchimp [4] 是最受欢迎的电子邮件服务之一,提供更好的交付率和数据分析。
在这里插入图片描述
图 10-6 显示了包含所有第三方服务后的设计。
在这里插入图片描述
联系信息收集流程
要发送通知,我们需要收集移动设备令牌、电话号码或电子邮件地址。如图 10-7 所示,当用户安装我们的应用进程或首次注册时,API 服务器收集用户联系信息并将其存储在数据库中。
在这里插入图片描述
图 10-8 显示了用于存储联系人信息的简化数据库表。电子邮件地址和电话数字存储在用户表中,而设备令牌存储在设备表中。一个用户可以有多个设备,表示可以向所有用户发送推送通知设备。
在这里插入图片描述
通知发送/接收流程
我们将首先介绍初始设计;然后,提出一些优化建议。
高级设计
设计如图 10-9 所示,下面对各个系统组件进行说明。
在这里插入图片描述
服务 1 到 N:服务可以是微服务、cron 作业或分布式系统,触发通知发送事件。例如,计费服务发送电子邮件提醒客户应付款或购物网站通过短信告诉客户他们的包裹将明天送达。
**通知系统:**通知系统是发送/接收的核心组建。从简单的事情开始,只使用一个通知服务器。它提供服务 1 到 N 的 API,并为第三方服务所需的有效载荷。
**第三方服务:**第三方服务负责将通知发送至用户。在集成第三方服务时,我们需要格外注意扩展。良好的可扩展性意味着一个灵活的系统,可以很轻松地插入或断开第三方服务。另一个重要的考虑因素是,可能在新市场或将来不可用第三方服务。例如,FCM 是在中国不可用。因此,使用了 Jpush、PushY 等替代第三方服务那里。
iOS、Android、短信、电子邮件:用户在其设备上接收通知。
此设计中发现了三个问题:

  • 单点故障 (SPOF):单个通知服务器意味着 SPOF。
  • 难以扩展:原始设计中所有与推送通知相关事务都由同一台服务器处理,而扩展数据库、缓存和不同类型的推送具有挑战性。
  • 性能瓶颈:处理和发送大量通知可能消耗大量资源,例如构建HTML页面并等待来自第三方响应可能需要时间。将所有事务集中处理会导致系统超载结果尤其在高峰时段。

高级设计(改进)
在列举了初始设计中的挑战后,我们改进了设计,如下所示:

  • 将数据库和缓存移出通知服务器。
  • 添加更多通知服务器并设置自动水平扩展。
  • 引入消息队列以解耦系统组件。

图 10-10 显示了改进的高级设计。
在这里插入图片描述
浏览上图的最佳方法是从左到右:
服务 1 到 N:它们表示通过 API 发送通知的不同服务通知服务器。
**通知服务器:**它们提供以下功能:

  • 为服务提供发送通知的 API。这些 API 只能在内部访问或由经过验证的客户端来防止垃圾邮件。
  • 进行基本验证以验证电子邮件、电话号码等。
  • 查询数据库或缓存以获取呈现通知所需的数据。
  • 将通知数据放入消息队列进行并行处理。
    下面是发送电子邮件的 API 示例:
    发布 https://api.example.com/v/sms/send
    请求正文
    在这里插入图片描述
    缓存:缓存用户信息、设备信息、通知模板。
    DB:它存储有关用户、通知、设置等的数据。
    消息队列:它们消除组件之间的依赖关系。消息队列充当当要发送大量通知时进行缓冲。每个通知类型是分配有不同的消息队列,因此第三方服务的中断不会影响其他通知类型。
    Workers:Workers 是从消息队列中拉取通知事件的服务器列表,将它们发送到相应的第三方服务。
    第三方服务:在最初的设计中已经解释过。
    iOS、Android、短信、电子邮件:已在初始设计中进行了解释。
    接下来,让我们检查一下每个组件如何协同工作来发送通知:
    1. 服务调用通知服务器提供的API发送通知。
    2. 通知服务器获取元数据,例如用户信息、设备令牌和通知来自缓存或数据库的设置。
    3. 将通知事件发送到相应的队列进行处理。例如,一个iOS 推送通知事件被发送到 iOS PN 队列。
    4. Workers 从消息队列中拉取通知事件。
    5. 工作人员向第三方服务发送通知。
    6. 第三方服务向用户设备发送通知。

第 3 步 - 设计深入研究

在高层设计中,我们讨论了不同类型的通知、联系信息收集流程和通知发送/接收流程。我们将深入探讨以下内容:

  • 可靠性。
  • 其他组件和注意事项:通知模板、通知设置、速率限制、重试机制、推送通知的安全性、监控排队通知和事件跟踪。
  • 更新设计。

可靠性
在设计通知系统时,我们必须回答一些关于分布式环境下重要的可靠性问题。
如何防止数据丢失?
通知系统最重要的要求之一是不能丢失数据。通知通常可以延迟或重新排序,但永远不会丢失。为了满足这个要求,通知系统将通知数据保存在数据库中并实现重试机制。包含通知日志数据库用于数据持久化,如图10-11。
在这里插入图片描述
收件人会只收到一次通知吗?
简短的回答是否定的。尽管大多数时候通知只发送一次,但分布式性质可能会导致重复通知。减少重复发生时,我们引入了重复数据删除机制,并仔细处理每个故障案例。这里是简单的重复数据删除逻辑:
当通知事件首次到达时,我们通过检查事件 ID 来检查它是否在之前出现过。如果之前看到过,则将其丢弃。否则,我们将发出通知。有兴趣的读者要了解为什幺我们不能一次交货,请参考参考资料[5].
其他组件和注意事项
我们已经讨论了如何收集用户联系信息、发送和接收通知。
答:A通知系统远不止于此。在这里,我们将讨论其他组件,包括模板重用、通知设置、事件跟踪、系统监控、速率限制等
通知模板
一个大型通知系统每天发送数百万条通知,其中许多通知通知遵循类似的格式。引入通知模板,避免构建从头开始的每个通知。通知模板是预先格式化的通知,用于通过自定义参数、样式、跟踪链接等创建您独特的通知。这里是推送通知的示例模板。
BODY:
You dreamed of it. We dared it. [ITEM NAME] is back — only until [DATE].
CTA:
Order Now. Or, Save My [ITEM NAME]
使用通知模板的好处包括保持一致的格式、减少误差,并节省时间。

通知设置
用户通常每天收到太多的通知,他们很容易感觉到淹没。因此,许多网站和应用进程为用户提供了对通知的精细控制设置。此信息存储在通知设置表中,其中包含以下字段:

user_id bigInt
channel varchar # 推送通知、电子邮件或短信
opt_in boolean # 选择接收通知

在向用户发送任何通知之前,我们首先检查用户是否选择接收此类型通知。

速率限制
为了避免用户被过多的通知淹没,我们可以限制的可以接收的通知用户数量。这很重要,因为如果我们发送得太频繁,接收器可能会关闭,则全部通知。
重试机制
当第三方服务发送通知失败时,该通知将被添加到Message Queue 进行重试。如果问题仍然存在,将向开发人员发送警报。
推送通知的安全性
对于 iOS 或 Android 应用,appKey 和 appSecret 用于保护推送通知 API[6]. 只有经过身份验证或验证的客户端才能使用我们的api。有兴趣的用户应参考参考资料 [6]。
监控排队的通知
排队通知的总数是要监视的一个关键指标。如果数量很大,工作人员处理通知事件的速度不够快。为避免延误通知传递,需要更多的工人。图 10-12(归功于 [7])显示了一个要处理的排队消息的示例。
在这里插入图片描述
事件跟踪
了解客户行为在以下方面很重要,通知指标(例如打开率、点击率和参与度)。分析服务实现事件跟踪。集成通常需要在通知系统和分析服务之间。图 10-13显示了可能出于分析目的而跟踪的事件示例。
在这里插入图片描述
更新的设计
将所有内容放在一起,图 10-14 显示了更新的通知系统设计。
在这里插入图片描述
在此设计中,与以前的设计相比,添加了许多新组件。

  • 通知服务器配备了两个更关键的功能:身份验证和速率限制。
  • 我们还添加了重试机制来处理通知失败。如果系统发送失败通知,它们将被放回消息队列中,工作线程将重试预定义的次数。
  • 此外,通知模板提供一致且高效的通知创建过程。
  • 最后,增加了监控和跟踪系统,用于系统健康检查和改进。

第 4 步 - 总结

通知是必不可少的,因为它们让我们随时了解重要信息。它可能是关于 Netflix 上您最喜欢的电影的推送通知、关于折扣的电子邮件有关新产品的信息,或有关您在线购物付款确认的消息。

在本章中,我们描述了一个可扩展的通知系统的设计,该系统支持多种通知格式:推送通知、短信、电子邮件。我们采用了消息队列来解耦系统组件。
除了高层设计之外,我们还深入挖掘了更多组件和优化。

  • 可靠性:我们提出了一种稳健的重试机制,以最大限度地降低故障率。
  • 安全性:AppKey/appSecret 对用于确保只有经过验证的客户端才能发送通知。
  • 跟踪和监控:这些在通知流的任何阶段实施,以便捕获重要统计数据。
  • 尊重用户设置:用户可以选择不接收通知。我们的系统检查在发送通知之前先进行用户设置。
  • 速率限制:用户接收也喜欢对通知数量设置频率上限。

恭喜您已经走到这一步了。好工作!
参考资料
[1] Twilio 短信:https://www.twilio.com/sms
[2] Nexmo 短信:https://www.nexmo.com/products/sms
[3]发送网格:https://sendgrid.com/
[4] Mailchimp:https://mailchimp.com/
[5] 你不能进行精确一次交付:https://bravenewgeek.com/you-cannot-have exactly-once-delivery/
[6] 推送通知的安全性:https://cloud.ibm.com/docs/services/mobilepush?
主题=移动推送通知安全性推送通知
[7]RadditMQ:https://bit.ly/2sotIa6

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端工匠之道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值