运行一组链

时间:2016-05-06 16:06:46

标签: celery

我试图在Celery中运行一组连锁店。我创建了一组链:

chains = [celery.chain(a.s(i), b.s(), c.s()) for i in items]

将此换行包装在一个组中:

group = celery.group(*chains)

这里的期望是,Celery将安排每个完整链作为一项独立任务运行。事实上,从逻辑上讲,这似乎发生了什么。但有两个问题:

  1. 如果链的数量很大,似乎没有任何东西可以运行。芹菜或rabbitmq游戏机没有错误。 (是的,使用rabbitmq。)

  2. 在转移到每个链的第二个任务之前,Celery似乎在组中的所有任务中执行每个链的第一个任务。 (也就是说,它似乎将链解包为一组任务a,任务b,然后是任务c。它们仍然链接到相应的链条目,但是,如果某个任务a的完成速度比其他任务快得多,则会导致延迟。

  3. 任何想法会发生什么?

1 个答案:

答案 0 :(得分:2)

一个非常有趣的问题!

  

我编写的代码用内存后端测试你的情况,只有一个进程(它在底部)celery -A module-name --loglevel=info -c 10

  1. 类似屏障的行为:这似乎不是问题。如果您应用不同的睡眠,或执行大量具有高并行性的任务,您将看到bc任务与a并行执行

  2. 在大型链上失败:当我尝试创建1000000个链时,代码实际上默默地在链创建时失败,所以它看起来更像是python内存问题。 100000长度的船很好

  3. 代码

    from celery import Celery, chain, group
    from pprint import pprint
    import threading
    from time import sleep
    
    app = Celery('chaintext')
    app.conf.update(
        BROKER_BACKEND = 'memory',
        CELERY_RESULT_BACKEND = 'cache',
        CELERY_CACHE_BACKEND  = 'memory',
        CELERY_EAGER_PROPAGATES_EXCEPTIONS = True,
        CELERY_TASK_SERIALIZER='json',
        CELERY_ACCEPT_CONTENT=['json'],  # Ignore other content
        CELERY_ENABLE_UTC=True,
        CELERYD_POOL = 'celery.concurrency.threads:TaskPool'
    )
    
    @app.task
    def a(i):
        result = 'A %s' % i
        sleep((i%3)/ 10.0)
        pprint(result)
        return result
    
    
    @app.task
    def b(self,i):
        result = 'B %s' % i    
        sleep((i%3)/  10.0)
        pprint(result)
        return result
    
    @app.task
    def c(self,i):
        result = 'C %s' % i
        sleep((i%3)/  10.0)
        pprint(result)
        return result
    
    def main():
        print "MAIN"
        import time
        time.sleep(5)
        print "STARTING"
        chains = [chain(a.s(i), b.s(i), c.s(i)) for i in range(1000000)]
        print "CREATED CHAINS"
        g = group(*chains)
        print "CREATED GROUP"
        result = g.apply_async()
        print "QUEUED GROUP"
    
        print result.get()
    
    t1 = threading.Thread(target=main)
    t1.start()