我在项目中使用Python和celery。在项目中,我有两个文件:
celeryconfig.py
BROKER_URL = "amqp://guest:guest@localhost:5672//"
CELERY_RESULT_BACKEND = "amqp"
CELERY_IMPORTS = ("example",)
CELERYD_CONCURRENCY = 2
和 example.py
from celery.task import task
import hashlib
md5 = hashlib.md5()
@task
def getDigest(text):
print 'Using md5 - ',md5
md5.update(text)
return md5.digest()
在 celeryconfig.py 中,我将 CELERYD_CONCURRENCY 设置为 2 ,这意味着它会将我的任务队列中的任务分配给< em> 2 不同的进程。
从Python控制台,我运行:
from example import getDigest
getDigest.delay('foo');getDigest.delay('bar')
这会创建两个由两个工作人员同时执行的任务。 问题是,当两个工作进程都运行其任务函数[ getDigest()]时,它们似乎使用相同的哈希对象( md5 )。 celeryd 的输出证实了这一点,如下所示。
[PoolWorker-2] Using md5 -
[PoolWorker-2] <md5 HASH object @ 0x23e6870>
[PoolWorker-1] Using md5 -
[PoolWorker-1] <md5 HASH object @ 0x23e6870>
为了简单起见,我使用的是hashlib的md5对象,但在我的实际项目中,我使用的对象不能可以被多个进程访问和修改。这预计会使工人崩溃。
这提出了一个问题:如何修改我的代码以使工作进程初始化并使用他们自己的( md5 )对象?现在,他们正在共享同一个对象 - 导致我的应用程序崩溃。这可能吗?
答案 0 :(得分:5)
他们使用相同的对象,因为您在代码中明确告诉他们。通过在任务范围之外创建对象并在任务中使用它,您将为所有工作者提供对共享对象的访问权限。这是一个并发问题,不一定是Celery问题。如果对象很小,您可以使用该对象的副本,或使用您自己的锁定策略。但是,一般情况下,如果一个对象一次要由多个进程更新,则需要采用某种同步,这超出了Celery的范围。