web-dev-qa-db-ja.com

Celeryのキュー内のタスクのリストを取得する

キュー内のまだ処理されていないタスクのリストを取得するにはどうすればよいですか?

126
bradley.ayers

編集:キュー内のタスクのリストを取得するための他の回答を参照してください。

こちらをご覧ください: セロリガイド-労働者の検査

基本的にこれ:

>>> 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()

あなたが望むものに応じて

163
semarj

rabbitMQを使用している場合、ターミナルでこれを使用します。

Sudo rabbitmqctl list_queues

キューのリストを保留中のタスクの数とともに出力します。例えば:

Listing queues ...
0b27d8c59fba4974893ec22d478a7093    0
0e0a2da9828a48bc86fe993b210d984f    0
[email protected] 0
11926b79e30a4f0a9d95df61b6f402f7    0
15c036ad25884b82839495fb29bd6395    1
[email protected]    0
celery  166
celeryev.795ec5bb-a919-46a8-80c6-5d91d2fcf2aa   0
celeryev.faa4da32-a225-4f6c-be3b-d8814856d1b6   0

右側の列の数字は、キュー内のタスクの数です。上記では、セロリキューには166個の保留中のタスクがあります。

40
Ali

優先順位付けされたタスクを使用しない場合、Redisを使用している場合、これは実際には かなり単純な です。タスクカウントを取得するには:

redis-cli -h Host -p PORT -n DATABASE_NUMBER llen QUEUE_NAME

しかし、優先順位付けされたタスク 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']))

逆シリアル化には少し時間がかかることがありますが、上記のコマンドを調整してさまざまな優先順位で動作する必要があることに注意してください。

15
mlissner

バックエンドからタスクを取得するには、これを使用します

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)
10
ashish

JSONシリアル化を使用したRedisのコピーアンドペーストソリューション:

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を変更することを忘れないでください。

6
Max Malysh

セロリ検査モジュールは、労働者の観点からのみタスクを認識しているように見えます。キューにあるメッセージを表示したい場合(ワーカーによってプルされる)、 pyrabbit を使用することをお勧めします。これは、rabbitmq http apiとインターフェースして、キュー。

例はここにあります: Celery(RabbitMQ、Django)でキューの長さを取得

4
Paul in 't Hout

待機中のタスクを取得する唯一の方法は、開始したタスクのリストを保持し、開始したタスクをリストから削除することです。

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で保存させ、どのタスクがそこにないかを確認します。

3
Sebastian Blask

Celery + Djangoを使用している場合、仮想環境で端末から直接コマンドを使用してタスクを検査する最も簡単な方法またはフルパスをセロリに使用:

Dochttp://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
3
om2c0de

私の知る限り、Celeryは、キューで待機しているタスクを調べるためのAPIを提供していません。これはブローカー固有です。たとえば、Redisをブローカーとして使用する場合、celery(デフォルト)キューで待機しているタスクを調べるのは次のように簡単です。

  1. ブローカーデータベースに接続する
  2. celeryリスト内の項目をリストします(例についてはLRANGEコマンド)

これらは利用可能な労働者によって選ばれるのを待っているタスクであることに留意してください。クラスターにはいくつかのタスクが実行されている可能性があります-それらは既に選択されているため、このリストには含まれません。

2
DejanLekic
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
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]))
1
Peter Shannon

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_projyour_projに変更するよう注意してください

0
sashaboulouds

タスクのコードを制御する場合は、タスクの初回実行時に簡単な再試行をトリガーし、inspect().reserved()をチェックすることで問題を回避できます。再試行はタスクを結果バックエンドに登録し、セロリはそれを見ることができます。再試行カウントにアクセスできるように、タスクはselfまたはcontextを最初のパラメーターとして受け入れる必要があります。

@task(bind=True)
def mytask(self):
    if self.request.retries == 0:
        raise self.retry(exc=MyTrivialError(), countdown=1)
    ...

このソリューションは、ブローカーに依存しません。 RabbitMQとRedisのどちらを使用してタスクを保存するかを心配する必要はありません。

編集:テスト後、これは部分的な解決策にすぎないことがわかりました。予約のサイズは、ワーカーのプリフェッチ設定に制限されます。

0
hedleyroos

打ち上げ花-seleryタスクのビューア

celery -A app.celery flower

そして、ブラウザで開きます

localhost:5555