Python 芹菜任务分组/聚合

Python 芹菜任务分组/聚合,python,asynchronous,task,celery,aggregation,Python,Asynchronous,Task,Celery,Aggregation,我计划使用芹菜来处理从主服务器发送推送通知和事件触发的电子邮件 这些任务需要打开与外部服务器(GCM、APS、电子邮件服务器等)的连接。它们可以一次处理一个,也可以通过单个连接批量处理,以获得更好的性能 通常,这些任务会在短时间内分别触发多个实例。例如,在一分钟内,可能会有几十个推送通知需要发送给具有不同消息的不同用户 用芹菜处理这个最好的方法是什么?似乎最天真的方法是对每条消息执行不同的任务,但这需要为每个实例打开一个连接 我希望会有某种任务聚合器允许我处理,例如“所有未完成的推送通知任务”

我计划使用芹菜来处理从主服务器发送推送通知和事件触发的电子邮件

这些任务需要打开与外部服务器(GCM、APS、电子邮件服务器等)的连接。它们可以一次处理一个,也可以通过单个连接批量处理,以获得更好的性能

通常,这些任务会在短时间内分别触发多个实例。例如,在一分钟内,可能会有几十个推送通知需要发送给具有不同消息的不同用户

用芹菜处理这个最好的方法是什么?似乎最天真的方法是对每条消息执行不同的任务,但这需要为每个实例打开一个连接

我希望会有某种任务聚合器允许我处理,例如“所有未完成的推送通知任务”

这样的事情存在吗?有没有更好的方法,比如加入一个活跃的任务组

我错过什么了吗


Robert

一种简单的方法是将任务应采取的所有操作写入持久性存储(如数据库),并让周期性作业在一个批处理中完成实际过程(使用单个连接)。 注意:确保您有一些适当的锁定,以防止队列被进程锁定两次

有一个很好的例子说明了如何在kombu级别执行类似的操作(http://ask.github.com/celery/tutorials/clickcounter.html)


就我个人而言,我喜欢sentry在db级别(sentry.buffers模块)进行批量增量处理的方式。

我最近发现并在我的项目中实现了
芹菜.contrib.batches
模块。在我看来,这是一个比Tommaso的答案更好的解决方案,因为您不需要额外的存储层

以下是一个例子:

一个单击计数器,每100条消息刷新一次缓冲区 秒。不处理数据,但可以轻松 修改为将其存储在数据库中


不过要小心,它对我的使用效果很好,但它在文档中提到这是一个“实验任务类”。这可能会阻止一些人使用具有如此易变描述的功能:)

澄清一下,这似乎是我想要的子任务的反面…独立调度但聚合处理的单个任务。非常好的发现!这里只有一点,您更喜欢它(未存储)的原因不适用于imo,而文档没有解释批处理是如何完成的,我看到了两种可能的方法:使用message broker或将其保存在内存中,如果工作人员崩溃,则可以很好地释放flush_every-1或flush_interval-1值的任务。仔细查看文档,似乎很清楚,它正在向broker发布每一个任务(请参阅关于CELERYD_PREFETCH_乘数的注释)和标记_as_done(task.id,task_result)并且当工作人员获得足够的任务时,它会在一个批中执行这些任务。我确实将预取乘数设置为0,但没有真正理解它。@TommasoBarbugli感谢您让我阅读它:)这看起来确实像是一个潜在的问题,尽管其中一个脚注提到了这一点“RabbitMQ和其他代理以循环方式传递消息,因此这不适用于活动系统。”。由于不了解芹菜或RabbitMQ,我不明白此设置为0是否存在实际问题。该页面已不存在;如果您将其更新为新页面,那就太好了。
# 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))