如何设计可扩展的通知系统?[关闭]


32

我需要写一个通知系统管理员。

这是我的要求:

我需要能够在可能完全不同的不同平台上发送通知(例如,我需要能够发送SMS或电子邮件)。

有时,对于给定平台的所有收件人,通知可能是相同的,但是有时,可能是每个平台(或多个)每个收件人的通知。

每个通知可以包含特定于平台的有效负载(例如,MMS可以包含声音或图像)。

系统需要可伸缩,我需要能够发送大量通知而不会导致应用程序或服务器崩溃。

这是一个分为两个步骤的过程,首先,客户可以输入消息并选择要发送到的平台,然后创建通知,以便稍后进行实时处理。

然后,系统需要将通知发送到平台提供商。


就目前而言,尽管我得到了一些结论,但是我不知道它的可扩展性或它是否是一个好的设计。

我有以下对象(使用伪语言):

通用Notification对象:

class Notification {
    String                 $message;
    Payload                $payload;
    Collection<Recipient>  $recipients;
}

如果我有1.000.000收件人,则以下对象的问题是什么?即使Recipient对象很小,也会占用太多内存。

我还可以为每个收件人创建一个通知,但是某些平台提供商要求我批量发送该通知,这意味着我需要定义一个包含多个收件人的通知。

每个创建的通知可以存储在诸如DB或Redis的持久性存储中。

稍后汇总此内容以确保其可伸缩性是否很好?

在第二步中,我需要处理此通知。

但是,如何区分通知给正确的平台提供商的通知呢?

我应该使用诸如MMSNotification扩展对象之类的对象abstract Notification吗?或类似的东西Notification.setType('MMS')

为了允许同时处理大量通知,我认为像RabbitMQ这样的消息传递队列系统可能是正确的工具。是吗?

这将使我可以排队很多通知,并有几个工作人员弹出通知并进行处理。但是,如果我需要如上所述对收件人进行批处理怎么办?

然后我想象NotificationProcessor的,我我可以添加对象NotificationHandler的每个NotificationHandler将负责连接平台提供商和执行通知。

我也可以使用EventManager允许插入行为。

有任何意见或建议吗?

感谢您抽出宝贵的时间。

注意:我曾经使用过PHP,并且它可能是我选择的语言。


编辑 (根据morphunreal的答案)

  • 您每秒发送多少消息(定义当前/初始级别,定义在重新设计之前系统应处理的最大级别)
  • 系统具有哪些硬件限制(内存,CPU等可供系统使用)
  • 硬件将如何扩展(即添加更多服务器,云计算等)

  • 哪些语言/系统将生成通知?

它是我自己的事情,我负责以编程方式创建通知,但该通知是通过用户界面构建的。

  • 生成器是否知道消息的收件人(?),还是通过其他某种方式提供消息(例如,某些警报类型的业务规则将发送给某些收件人)

应该可以为特定收件人,一组收件人(例如,使用标签系统)或整个平台创建通知。

  • 是否有添加CC / BCC /阅读收据的业务规则

是。请注意,这实际上是特定于平台的,read或cc并非在所有平台上都可用。

  • 生成器是否知道其发送的消息类型(例如,SMS /电子邮件),还是基于收件人?

它基于接收者,但是,由于接收者与平台相关,并且平台具有不同的数据处理方式,因此UI可能是特定于平台的,以允许设置图像,声音或其他内容。

  • 生成器是否要求确认正在发送/接收/读取的消息(异步与同步发送)

嗯,系统应该易于出错,但是我们想处理错误以定义一组规则,例如,如果服务器不可达,则应重新安排通知的队列以进行进一步处理,但是如果通知不正确(或已经被通知)由平台提供商定义),不应重新排队,而应通知它。

  • 是否有存储消息源/收件人历史记录的要求(需要多长时间?)

是的,我们可能希望进行一些统计和报告。*定义通知端点


  • 正在使用什么服务来发送消息?取决于,一些是经典的REST Web服务,其他是一些奇特的协议,这实际上取决于提供者。

  • 提供什么反馈/确认(同步/异步)

视情况而定,有些是同步的并有错误答复,而其他一些则需要稍后拉出以检查错误。

  • 是否有可能添加新的端点[即使是,甚至还需要抽象]

是的,实际上,我们的应用程序正在增长,我们可能希望能够添加新的提供商,但这比率每年约为1或2。


22
Walter,gnat,gbjbaanb,Robert Harvey,thorstenmüller似乎很懒惰;我看不出有以下任何一种理由可以解决此问题:“模棱两可,含糊不清,不完整,过于宽泛或夸张”。设计问题不可能是一个简单的问题,因为它涉及到很多事情,尽管本网站的水平允许如此复杂的决定与真正的专业人员进行讨论。
特伦特

问问题但不要问问题!:)是的,有时候我也无法理解mod的心态。
Mrchief 2015年

投票和看法表明这个问题有多重要。...如果只有主持人一定会理解!!!
NoobEditor

使用RabbitMQ是解决此问题的正确方法。在BIG公司的一次采访中,我被问到非常类似的问题,并且我一直在努力寻求最佳的容错发布者/订阅者模式。最后,我被告知正确答案。RabbitMQ。好像他们已经使用它解决了问题。希望有帮助!!!
AkD

Answers:


16

首先分离出功能需求和非功能需求,并仔细定义它们。根据模棱两可的要求过度设计系统非常容易。

例如,您对可伸缩性的非功能性要求非常含糊。如果在系统上放置实际数字,则可以减轻很多精神负担。例如,

  • 您每秒发送多少消息(定义当前/初始级别,定义在重新设计之前系统应处理的最大级别)
  • 系统具有哪些硬件限制(内存,CPU等可供系统使用)
  • 硬件将如何扩展(即添加更多服务器,云计算等)

既然您已将其排除在外,就可以设置一些测试以确保系统设计/体系结构能够满足您的非功能性需求。

至于发送通知/消息的业务/功能要求,以下提示可能会有所帮助(如果您提供更多信息,我可以添加到此答案中):

定义通知源

  • 哪种语言/系统将生成通知
  • 生成器是否知道消息的收件人(?),还是通过其他某种方式提供消息(例如,某些警报类型的业务规则将发送给某些收件人)
  • 是否有添加CC / BCC /阅读收据的业务规则
  • 生成器是否知道其发送的消息类型(例如,SMS /电子邮件),还是基于收件人?
  • 生成器是否要求确认正在发送/接收/读取的消息(异步与同步发送)
  • 是否有存储消息源/收件人历史记录的要求(需要多长时间?)

定义通知端点

  • 正在使用哪些服务发送消息
  • 提供什么反馈/确认(同步/异步)
  • 是否有可能添加新的端点[即使是,甚至还需要抽象]

我不愿提供一个具体的架构示例,因为它在很大程度上取决于所涉及的因素。但是最简单的消息系统通常会在内存/应用程序,no-SQL,磁盘或关系数据库中涉及一个基本队列。然后,一个单独的进程(或几个单独的进程,如果分布)可以轮询队列以获取其消息类型(即cron作业);并根据需要发送。

如果需要立即发送消息,则可以使用一些基于推送的技术(即PostgreSQL NOTIFY / LISTEN)来增强此功能。

简单队列的优点在于,生成消息的系统要做的工作很少,并且可以基于硬件/性能要求来平衡处理系统。


非常感谢您的详细回答,这实际上有助于我提出一些更清晰的想法。我修改了答案,以回答您提出的问题。
特伦特(Trent)

-2

您是否考虑过通知对象的举重设计模式?我对此不太确定,因为我从未实现过该模式,但是我记得它涉及在举重对象之间共享一些状态。我也认为,如果共享,冗余度更高的成员会产生更大的影响。因此,这取决于您是否仅向许多人发送少量消息,反之亦然。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.