使用队列还是应用程序级别执行延迟任务更好

95次阅读
没有评论

问题描述

在尝试扩展推送通知基础设施时,有一个问题是在执行延迟任务时,是使用队列还是在应用程序级别执行更好。他们目前使用的是在两个EC2实例上水平扩展的Laravel应用程序,每个实例都有一个Beanstalk队列引擎来处理Laravel创建的任务(包括推送通知任务)。
问题是这种解决方案的性能不佳。有时我们会向所有客户发送营销推送通知,数量可能达到数千条,第一条推送通知和最后一条推送通知之间的时间差可能会达到几个小时。
用户考虑了一些基础设施的选择。他们考虑使用AWS SQS,但发现它的最大延迟任务容量为15分钟。在用户的业务中,客户可以提前20小时预订。所以他们目前的做法是计划一个20小时后的延迟任务。
但是有人建议延迟部分应该只在应用程序级别处理(例如delay(work, timedelta(hours=20))),这样可以使用SQS。他们的理由是延迟任务是业务逻辑的一部分,最好在应用程序级别处理,而不是在基础设施级别处理。
用户不确定是否同意这个观点,所以他们在考虑使用AWS Elastic Cache和Redis。他们想知道大家的意见。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

在这种情况下,我建议使用调度程序来安排任务的执行,而不是构建延迟执行的逻辑。调度程序还可以提供状态更新的额外优势。考虑使用AWS的Simple Workflow Service(SWF)。
以下是一种可能的解决方案:
1. 使用SWF来调度任务的执行。SWF可以与Lambda函数一起使用,这样您就不必担心Lambda的扩展性问题。
2. 将通知存储在某个地方,例如数据库表或Redis服务。在通知中记录发送时间。
3. 编写一个Lambda函数,定期检查需要发送的通知,并将其发送到SQS队列。这样,如果发送失败,可以利用SQS的重试机制。
4. 在应用程序中,可以使用另一个应用程序或Lambda函数来检查通知并发送它们。
这种方法可以确保应用程序在通知被声明和被缓存确认后,可以正确地注册并在需要时触发通知,并在发送失败时进行重试。

方案2

另一种方法是在应用程序级别处理延迟任务。您可以在应用程序中使用延迟函数来处理延迟逻辑,然后将通知发送到SQS队列。
以下是一种可能的解决方案:
1. 在应用程序中,使用延迟函数来安排任务的执行。例如,在Python中,可以使用delay(work, timedelta(hours=20))来延迟任务的执行。
2. 将延迟任务发送到SQS队列。这样,您可以利用SQS的重试机制来处理发送失败的情况。
3. 编写一个消费者应用程序或Lambda函数,从SQS队列中获取延迟任务并执行。
这种方法将延迟任务的处理逻辑放在应用程序中,使得业务逻辑更清晰,并且可以利用SQS的重试机制来处理发送失败的情况。

方案3

请注意,这是一个意见性的问题,不同的人可能有不同的观点。
另一种选择是使用AWS Elasticache和Redis来存储通知,并使用Lambda函数定期检查并发送通知。这种方法可以根据您和您的团队的偏好和熟悉程度来选择。
请注意,无论您选择哪种方法,都需要确保通知在发送之前经过适当的验证和处理,以避免发送无效的通知或重复发送通知。

正文完