我有一个任务需要从触发它的网页异步运行。这个任务运行的时间很长,并且由于网页可能会收到很多这样的请求,我希望 celery 在给定的时间只运行这个任务的一个实例。
有什么办法可以在 Celery 本地做到这一点?我很想创建一个数据库表来保存所有要与之通信的任务的状态,但感觉很hacky。
我有一个任务需要从触发它的网页异步运行。这个任务运行的时间很长,并且由于网页可能会收到很多这样的请求,我希望 celery 在给定的时间只运行这个任务的一个实例。
有什么办法可以在 Celery 本地做到这一点?我很想创建一个数据库表来保存所有要与之通信的任务的状态,但感觉很hacky。
您可能可以为配置了 CELERYD_CONCURRENCY=1 的任务创建一个专用的工作人员,然后该工作人员上的所有任务将同步运行
您可以为此使用 memcache/redis。celery 官方网站上有一个例子 - http://docs.celeryproject.org/en/latest/tutorials/task-cookbook.html
如果你更喜欢 redis(这是一个 Django 实现,但你也可以根据需要轻松修改它):
from django.core.cache import cache
from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)
class SingletonTask(Task):
def __call__(self, *args, **kwargs):
lock = cache.lock(self.name)
if not lock.acquire(blocking=False):
logger.info("{} failed to lock".format(self.name))
return
try:
super(SingletonTask, self).__call__(*args, **kwargs)
except Exception as e:
lock.release()
raise e
lock.release()
然后将其用作基本任务:
@shared_task(base=SingletonTask)
def test_task():
from time import sleep
sleep(10)
这种实现是非阻塞的。如果您希望下一个任务等待上一个任务更改blocking=False
并blocking=True
添加timeout