我打算使用Celery来处理发送来自我的主服务器的事件触发的推送通知和电子邮件。
这些任务需要打开与外部服务器(GCM,APS,电子邮件服务器等)的连接。它们可以一次处理一个,也可以通过单个连接批量处理,以获得更好的性能。
通常会在短时间内单独触发这些任务的几个实例。例如,在一分钟的时间内,可能会有几十个推送通知需要通过不同的消息发送给不同的用户。
在Celery中处理此问题的最佳方法是什么?似乎天真的方法是为每条消息设置不同的任务,但这需要为每个实例打开一个连接。
我希望会有某种任务聚合器允许我处理例如'所有出色的推送通知任务'。
这样的事情存在吗?有没有更好的方法来解决它,例如附加到活动的任务组?
我错过了什么吗?
罗伯特
答案 0 :(得分:8)
我最近发现并在我的项目中实现了celery.contrib.batches
模块。在我看来,它比Tommaso的答案更好,因为你不需要额外的存储层。
以下是straight from the docs示例:
一个点击计数器,每隔100条消息刷新一次缓冲区 秒。对数据没有任何作用,但可以轻松实现 修改后将其存储在数据库中。
# Flush after 100 messages, or 10 seconds.
@app.task(base=Batches, flush_every=100, flush_interval=10)
def count_click(requests):
from collections import Counter
count = Counter(request.kwargs['url'] for request in requests)
for url, count in count.items():
print('>>> Clicks: {0} -> {1}'.format(url, count))
要小心,它可以正常使用,但它提到这是文档中的“实验任务类”。这可能会阻止一些人使用具有这种易变性描述的特征:)
答案 1 :(得分:4)
实现此目的的一种简单方法是编写任务应在持久存储(例如数据库)上执行的所有操作,并让定期作业在一个批处理中执行实际过程(使用单个连接)。 注意:确保您有一些锁定以防止队列进行两次处理!
关于如何在kombu级别做类似的事情有一个很好的例子(http://ask.github.com/celery/tutorials/clickcounter.html)
就我个人而言,我喜欢sentry做这样的事情,以便在db级别进行批量增量(sentry.buffers模块)