如何检索队列中尚未处理的任务列表?
答案 0 :(得分:158)
编辑:请参阅其他答案以获取队列中的任务列表。
你应该看看这里: Celery Guide - Inspecting Workers
基本上这个:
>>> from celery.task.control import inspect
# Inspect all nodes.
>>> i = inspect()
# Show the items that have an ETA or are scheduled for later processing
>>> i.scheduled()
# Show tasks that are currently active.
>>> i.active()
# Show tasks that have been claimed by workers
>>> i.reserved()
取决于您想要的内容
答案 1 :(得分:39)
如果您使用的是RabbitMQ,请在终端中使用:
sudo rabbitmqctl list_queues
它将打印具有待处理任务数的队列列表。例如:
Listing queues ...
0b27d8c59fba4974893ec22d478a7093 0
0e0a2da9828a48bc86fe993b210d984f 0
10@torob2.celery.pidbox 0
11926b79e30a4f0a9d95df61b6f402f7 0
15c036ad25884b82839495fb29bd6395 1
celerey_mail_worker@torob2.celery.pidbox 0
celery 166
celeryev.795ec5bb-a919-46a8-80c6-5d91d2fcf2aa 0
celeryev.faa4da32-a225-4f6c-be3b-d8814856d1b6 0
右列中的数字是队列中的任务数。在上面,芹菜队列有166个待处理任务。
答案 2 :(得分:14)
如果您没有使用优先级排序的任务,那么如果您使用的是Redis,则实际上是pretty simple。要完成任务计数:
redis-cli -h HOST -p PORT -n DATABASE_NUMBER llen QUEUE_NAME
但是,优先任务use a different key in redis,所以整体情况稍微复杂一些。全貌是您需要为每个任务优先级查询redis。在python(以及Flower项目)中,这看起来像:
PRIORITY_SEP = '\x06\x16'
DEFAULT_PRIORITY_STEPS = [0, 3, 6, 9]
def make_queue_name_for_pri(queue, pri):
"""Make a queue name for redis
Celery uses PRIORITY_SEP to separate different priorities of tasks into
different queues in Redis. Each queue-priority combination becomes a key in
redis with names like:
- batch1\x06\x163 <-- P3 queue named batch1
There's more information about this in Github, but it doesn't look like it
will change any time soon:
- https://github.com/celery/kombu/issues/422
In that ticket the code below, from the Flower project, is referenced:
- https://github.com/mher/flower/blob/master/flower/utils/broker.py#L135
:param queue: The name of the queue to make a name for.
:param pri: The priority to make a name with.
:return: A name for the queue-priority pair.
"""
if pri not in DEFAULT_PRIORITY_STEPS:
raise ValueError('Priority not in priority steps')
return '{0}{1}{2}'.format(*((queue, PRIORITY_SEP, pri) if pri else
(queue, '', '')))
def get_queue_length(queue_name='celery'):
"""Get the number of tasks in a celery queue.
:param queue_name: The name of the queue you want to inspect.
:return: the number of items in the queue.
"""
priority_names = [make_queue_name_for_pri(queue_name, pri) for pri in
DEFAULT_PRIORITY_STEPS]
r = redis.StrictRedis(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DATABASES['CELERY'],
)
return sum([r.llen(x) for x in priority_names])
如果您想获得实际任务,可以使用以下内容:
redis-cli -h HOST -p PORT -n DATABASE_NUMBER lrange QUEUE_NAME 0 -1
从那里你必须反序列化返回的列表。就我而言,我能够通过以下方式实现这一目标:
r = redis.StrictRedis(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DATABASES['CELERY'],
)
l = r.lrange('celery', 0, -1)
pickle.loads(base64.decodestring(json.loads(l[0])['body']))
请注意,反序列化可能需要一些时间,并且您需要调整上面的命令以使用各种优先级。
答案 3 :(得分:10)
要从后端检索任务,请使用此
from amqplib import client_0_8 as amqp
conn = amqp.Connection(host="localhost:5672 ", userid="guest",
password="guest", virtual_host="/", insist=False)
chan = conn.channel()
name, jobs, consumers = chan.queue_declare(queue="queue_name", passive=True)
答案 4 :(得分:5)
Redis的复制粘贴解决方案,带有json序列化:
def get_celery_queue_items(queue_name):
import base64
import json
# Get a configured instance of a celery app:
from yourproject.celery import app as celery_app
with celery_app.pool.acquire(block=True) as conn:
tasks = conn.default_channel.client.lrange(queue_name, 0, -1)
decoded_tasks = []
for task in tasks:
j = json.loads(task)
body = json.loads(base64.b64decode(j['body']))
decoded_tasks.append(body)
return decoded_tasks
它适用于Django。别忘了改变yourproject.celery
。
答案 5 :(得分:4)
芹菜检查模块似乎只是从工人的角度了解这些任务。如果你想查看队列中的消息(尚未被工作人员提取),我建议使用pyrabbit,它可以与rabbitmq http api连接,以从队列中检索所有类型的信息。 / p>
可以在这里找到一个例子: Retrieve queue length with Celery (RabbitMQ, Django)
答案 6 :(得分:3)
我认为获取正在等待的任务的唯一方法是保留您启动的任务列表,并让任务在启动时从列表中删除。
使用rabbitmqctl和list_queues,您可以了解等待的任务数量,但不是任务本身:http://www.rabbitmq.com/man/rabbitmqctl.1.man.html
如果您想要的任务包括正在处理但尚未完成的任务,您可以保留一份任务列表并检查其状态:
from tasks import add
result = add.delay(4, 4)
result.ready() # True if finished
或者你让Celery用CELERY_RESULT_BACKEND存储结果并检查你的哪些任务不在那里。
答案 7 :(得分:2)
据我所知,Celery没有提供用于检查队列中等待任务的API。这是特定于经纪人的。如果您使用Redis作为示例的代理,那么检查在celery
(默认)队列中等待的任务就像这样简单:
celery
列表中的项目(例如LRANGE命令)请记住,这些任务是等待可用工作人员选择的任务。您的群集可能正在运行某些任务 - 这些任务将不在此列表中,因为它们已被选中。
答案 8 :(得分:1)
我得出结论,获取队列中的作业数量的最佳方法是使用rabbitmqctl
,这在此已多次提出。要允许任何选定的用户使用sudo
运行命令,我按照说明here(我确实跳过了编辑个人资料部分,因为我不介意在命令之前键入sudo。)
我还抓住了jamesc的grep
和cut
代码段并将其包装在子进程调用中。
from subprocess import Popen, PIPE
p1 = Popen(["sudo", "rabbitmqctl", "list_queues", "-p", "[name of your virtula host"], stdout=PIPE)
p2 = Popen(["grep", "-e", "^celery\s"], stdin=p1.stdout, stdout=PIPE)
p3 = Popen(["cut", "-f2"], stdin=p2.stdout, stdout=PIPE)
p1.stdout.close()
p2.stdout.close()
print("number of jobs on queue: %i" % int(p3.communicate()[0]))
答案 9 :(得分:1)
如果您使用的是 Celery + Django 的最简单方法来检查任务,直接在虚拟环境中从终端输入命令,或者使用完整路径 >芹菜:
文档:http://docs.celeryproject.org/en/latest/userguide/workers.html?highlight=revoke#inspecting-workers
$ celery inspect reserved
$ celery inspect inspect
$ celery inspect registered
$ celery inspect scheduled
如果您正在使用 Celery + RabbitMQ ,则可以使用以下命令检查队列列表:
更多信息:https://linux.die.net/man/1/rabbitmqctl
$ sudo rabbitmqctl list_queues
答案 10 :(得分:0)
如果您控制任务的代码,则可以通过以下方法来解决该问题:让任务在首次执行时触发一次重试,然后选中inspect().reserved()
。重试将任务注册到结果后端,而celery可以看到。该任务必须接受self
或context
作为第一个参数,以便我们可以访问重试计数。
@task(bind=True)
def mytask(self):
if self.request.retries == 0:
raise self.retry(exc=MyTrivialError(), countdown=1)
...
此解决方案与代理无关,即。您不必担心是使用RabbitMQ还是Redis存储任务。
编辑:经过测试,我发现这只是部分解决方案。保留的大小限制为工作者的预取设置。
答案 11 :(得分:0)
启动鲜花-查看任务
celery -A app.celery flower
然后在浏览器中打开
localhost:5555
答案 12 :(得分:0)
from celery.task.control import inspect
def key_in_list(k, l):
return bool([True for i in l if k in i.values()])
def check_task(task_id):
task_value_dict = inspect().active().values()
for task_list in task_value_dict:
if self.key_in_list(task_id, task_list):
return True
return False
答案 13 :(得分:0)
使用subprocess.run
:
import subprocess
import re
active_process_txt = subprocess.run(['celery', '-A', 'my_proj', 'inspect', 'active'],
stdout=subprocess.PIPE).stdout.decode('utf-8')
return len(re.findall(r'worker_pid', active_process_txt))
请注意将my_proj
更改为your_proj
答案 14 :(得分:0)
这在我的应用程序中对我有用:
def get_celery_queue_active_jobs(queue_name):
connection = <CELERY_APP_INSTANCE>.connection()
try:
channel = connection.channel()
name, jobs, consumers = channel.queue_declare(queue=queue_name, passive=True)
active_jobs = []
def dump_message(message):
active_jobs.append(message.properties['application_headers']['task'])
channel.basic_consume(queue=queue_name, callback=dump_message)
for job in range(jobs):
connection.drain_events()
return active_jobs
finally:
connection.close()
active_jobs
将是与队列中的任务相对应的字符串列表。
别忘了与自己的交换出CELERY_APP_INSTANCE。
感谢@ashish将我的答案指向正确的方向:https://stackoverflow.com/a/19465670/9843399