Service 构建可配置的用户通知服务

Service 构建可配置的用户通知服务,service,notifications,cron,alert,jobs,Service,Notifications,Cron,Alert,Jobs,我正在构建一个应用程序,它需要在一天中的固定时间向用户发送通知。用户可以选择在一天中的哪个时间收到通知,以及在哪几天收到通知。例如,用户可能希望每天早上6点收到通知,或者仅在工作日早上7点收到通知 在后端,我不确定如何构建发送这些通知的服务。解决方案需要处理: 并发性,因此我可以扩展我的服务器(通知不应重复) 系统重新启动 如果用户更改其首选项,则应重新安排挂起的通知 正如我所看到的,您需要有3种类型的实体:用户(存储电子邮件或以其他方式联系用户)、通知(存储您要发送给用户的内容-文本等)和计

我正在构建一个应用程序,它需要在一天中的固定时间向用户发送通知。用户可以选择在一天中的哪个时间收到通知,以及在哪几天收到通知。例如,用户可能希望每天早上6点收到通知,或者仅在工作日早上7点收到通知

在后端,我不确定如何构建发送这些通知的服务。解决方案需要处理:

  • 并发性,因此我可以扩展我的服务器(通知不应重复)
  • 系统重新启动
  • 如果用户更改其首选项,则应重新安排挂起的通知

正如我所看到的,您需要有3种类型的实体:用户(存储电子邮件或以其他方式联系用户)、通知(存储您要发送给用户的内容-文本等)和计划(在用户希望获得通知时存储)。您需要将这些类型的实体存储在某种数据库中。 计划应连接到用户,通知应连接到用户和计划

假设您有cron作业,它每分钟启动一些脚本。此脚本将尝试获取与当前时间(作业开始时间)的计划相关的所有通知。不要忘记实施某种类型的重叠预防

在此之后,脚本将把一个任务(包含所有需要的数据:通知类型、要通知的用户等)放入队列(beanstalkd或其他内容)。您可以创建任意数量的worker(即使在不同的物理实例上),以服务于此队列(不考虑重复)-这将为您提供强大的可伸缩性

如果用户更改了日程安排,将同时影响其所有通知。没有未决通知,因为只有在确实应该发送通知时才会发送通知


这是一个非常高级的描述。许多事情取决于语言、数据库、队列服务器、wokers实现。

使用消息代理(如)和任务调度器(如)可能满足您的要求

异步或非阻塞处理是将某些任务的执行与程序的主流分离的一种方法。这为您提供了几个优势,包括允许面向用户的代码无中断运行

消息传递是程序组件用来通信和交换信息的一种方法。它可以同步或异步实现,并且可以允许离散进程毫无问题地通信。对于这种类型的使用,消息传递通常作为传统数据库的替代方案实现,因为消息队列通常实现附加功能,提供更高的性能,并且可以完全驻留在内存中

芹菜是建立在异步消息传递系统上的任务队列。它可以用作一个bucket,在这里可以转储编程任务。通过任务的程序可以继续执行并响应功能,然后,它可以轮询芹菜以查看计算是否完成并检索数据

芹菜是用Python编写的,它的协议可以用任何语言实现。worker是Python中芹菜的一个实现。如果该语言有一个AMQP客户机,那么用您的语言创建一个worker应该不会有太多工作。芹菜工作者只是一个连接到代理以处理消息的程序

另外,还有另一种独立于语言的方法,那就是使用REST任务,而不是将任务作为函数,它们是URL。有了这些信息,您甚至可以创建简单的web服务器来支持代码预加载。只需公开一个执行操作的端点,并创建一个只对该端点执行HTTP请求的任务

下面是官方发布的python示例:


用户将以何种方式接收通知?电子邮件、Android/iOS推送通知,还有其他吗?@robbat2通知的类型在这里并不重要。这只是构建一个系统,它为您提供了一个钩子,让您可以按计划异步执行某些操作。作为记录,我将发送web推送通知和/或电子邮件。您没有指定平台/OS。任何后端语言和任何数据库。:-)
from celery import Celery
from celery.schedules import crontab

app = Celery()

@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    # Calls test('hello') every 10 seconds.
    sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')

    # Calls test('world') every 30 seconds
    sender.add_periodic_task(30.0, test.s('world'), expires=10)

    # Executes every Monday morning at 7:30 a.m.
    sender.add_periodic_task(
        crontab(hour=7, minute=30, day_of_week=1),
        test.s('Happy Mondays!'),
    )

@app.task
def test(arg):
    print(arg)