我正在使用Celery + RabbitMQ 当Celery工作人员不可用时,所有任务都在RabbitMQ中等待 正如它变得在线一样,所有这些任务都会立即执行 我可以以某种方式阻止它发生吗?
例如,有等待Celery工作人员的100个任务(相同),当Celery工作人员上线时,我可以只执行其中一个吗?
答案 0 :(得分:2)
由于队列中的所有任务都相同,更好的方法是仅发送一次,为此,您需要能够跟踪任务是否已发布,例如:
使用自定义任务ID和自定义状态,例如:
在发布任务时添加自定义状态:
from celery import current_app
from celery.signals import after_task_publish
@after_task_publish.connect
def add_sent_state(sender=None, body=None, **kwargs):
"""Track Published Tasks."""
# get the task instance from its name
task = current_app.tasks.get(sender)
# if there is no task.backend fallback to app.backend
backend = task.backend if task else current_app.backend
# store the task state
backend.store_result(body['id'], None, 'SENT')
当您要发送任务时,您可以检查任务是否已发布,并且由于我们使用自定义状态,因此任务的状态不会是PENDING
当它发布时(可能是未知的)所以我们可以使用:
from celery import states
# the task has a custom ID
task = task_func.AsyncResult('CUSTOM_ID')
if task.state != states.PENDING:
# the task already exists
else:
# send the task
task_func.apply_async(args, kwargs, task_id='CUSTOM_ID')
我在我的应用中使用这种方法并且工作得很好,我的任务可以多次发送,并且可以通过ID标识,这样每个任务都会发送一次。
如果您仍想取消队列中的所有任务,可以使用:
# import your Celery instance
from project.celery import app
app.control.purge()
答案 1 :(得分:1)
有两种方法可以做到这一点。
首先,只运行一个并发为1的worker。
celery worker -A your_app -l info -c 1
此命令启动并发为1的worker。因此,一次只能执行一项任务。这是首选方法。
第二种方法有点复杂。您需要获取锁定并释放锁定以确保仅one task is executed at a time。
或者,如果需要,可以使用purge
命令从队列中删除所有任务。
celery -A your_app purge