Celery에서 대기열에있는 작업 목록 검색


147

아직 처리되지 않은 대기열의 작업 목록을 어떻게 검색합니까?


1
RabbitMQ,하지만 파이썬 에서이 목록을 검색하고 싶습니다.
bradley.ayers

답변:


174

편집 : 대기열에서 작업 목록을 얻는 다른 답변을 참조하십시오.

현재 같아야합니다 셀러리 가이드 -의 검사 노동자

기본적으로 이것은 :

from celery.app.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()

원하는 것에 따라


9
나는 그것을 시도했지만 실제로 1 초와 같이 느리다. 토네이도 앱에서 진행 상황을 모니터링하기 위해 동시에 사용하므로 속도가 빠릅니다.
JulienFr

41
아직 처리되지 않은 대기열의 작업 목록은 반환하지 않습니다.
Ed J

9
i.reserved()대기중인 작업 목록을 얻는 데 사용 합니다.
바나나

4
i.reserved ()에 정확한 작업 목록이 없다는 것을 경험 한 사람이 있습니까? 목록에 표시되지 않는 작업이 실행 중입니다. 나는 django-celery == 3.1.10에있다
Seperman

6
작업자를 지정할 때 목록을 인수로 사용해야했습니다 inspect(['celery@Flatty']). 이상으로 빠른 속도 개선 inspect().
Adversus

42

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 개의 보류중인 작업이 있습니다.


1
sudo 권한이있을 때 이것에 익숙하지만 권한이없는 시스템 사용자가 어떤 제안을 확인할 수 있기를 바랍니다.
현인

또한이 파이프를 통해 나중에 해당 숫자를 처리하려는 경우 통계 grep -e "^celery\s" | cut -f2를 추출 할 166수 있습니다.
jamesc

21

우선 순위가 지정된 작업을 사용하지 않으면 Redis를 사용하는 경우 실제로 매우 간단 합니다. 작업 수를 얻으려면 :

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

그러나 우선 순위가 지정된 작업 은 redis에서 다른 키를 사용 하므로 전체 그림이 약간 더 복잡합니다. 전체 그림은 모든 작업 우선 순위에 대해 redis를 쿼리해야한다는 것입니다. 파이썬과 꽃 프로젝트에서 다음과 같이 보입니다.

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']))

역 직렬화에는 다소 시간이 걸릴 수 있으므로 위의 명령을 조정하여 다양한 우선 순위로 작업해야합니다.


이것을 프로덕션 환경에서 사용한 후 Celery의 설계로 인해 우선 순위가 지정된 작업을 사용하면 실패 한다는 것을 알게되었습니다 .
mlissner

1
우선 순위가 지정된 작업을 처리하기 위해 위의 내용을 업데이트했습니다. 진행!
mlissner

1
그냥 물건을 밖으로 철자하는 DATABASE_NUMBER기본값은에 의해 사용 0하고 QUEUE_NAME있다 celery, 그래서 redis-cli -n 0 llen celery대기중인 메시지의 수를 반환합니다.
Vineet Bansal

셀러리의 경우 대기열 이름이 '{{{0}}}{1}{2}'대신입니다 '{0}{1}{2}'. 그 외에는 완벽하게 작동합니다!
zupo

12

백엔드에서 작업을 검색하려면 다음을 사용하십시오.

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)

2
그러나 '작업'은 대기열에있는 많은 작업 만 제공합니다
bitnik

작업 이름을 제공하는 관련 답변 은 stackoverflow.com/a/57807913/9843399 를 참조하십시오 .
Caleb Syring

10

당신이 사용하는 경우 셀러리 + 장고 작업을 당신의 터미널에서 직접 명령을 사용하여 검사하는 간단한 방법을 가상 환경 또는 사용하여 전체 경로 셀러리로를 :

문서 : http://docs.celeryproject.org/en/latest/userguide/workers.html?highlight=revoke#inspecting-workers

$ celery inspect reserved
$ celery inspect active
$ celery inspect registered
$ celery inspect scheduled

또한 Celery + RabbitMQ 를 사용하는 경우 다음 명령을 사용하여 큐 목록을 검사 할 수 있습니다 .

자세한 정보 : https://linux.die.net/man/1/rabbitmqctl

$ sudo rabbitmqctl list_queues

4
정의 프로젝트가있는 경우 다음을 사용할 수 있습니다.celery -A my_proj inspect reserved
sashaboulouds

6

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

장고와 함께 작동합니다. 변경하는 것을 잊지 마십시오 yourproject.celery.


1
피클 직렬 변환기를 사용하는 경우 body =회선을로 변경할 수 있습니다 body = pickle.loads(base64.b64decode(j['body'])).
Jim Hunziker


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로 결과를 저장하도록하고 거기에없는 작업을 확인하십시오.


3

이것은 내 응용 프로그램에서 나를 위해 일했습니다.

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를 자신의 것으로 바꾸는 것을 잊지 마십시오.

https://stackoverflow.com/a/19465670/9843399 여기에 그의 대답으로 올바른 방향으로 나를 가리켜 주신 @ashish에게 감사드립니다.


제 경우 jobs에는 항상 제로입니다 ... 어떤 생각입니까?
daveoncode

@daveoncode 나는 그것이 도움이 될만한 충분한 정보라고 생각하지 않습니다. 당신은 당신의 자신의 질문을 열 수 있습니다. 파이썬에서 정보를 검색하도록 지정하면이 복제본이라고 생각하지 않습니다. 나는 stackoverflow.com/a/19465670/9843399 로 돌아가서 내 대답을 기반으로하고 그것이 먼저 작동하는지 확인하십시오.
갈렙

@CalebSyring 대기중인 작업을 실제로 보여주는 첫 번째 방법입니다. 아주 좋아요 나에게 유일한 문제는 목록 추가가 작동하지 않는 것입니다. 콜백 함수를 목록에 쓰는 방법은 무엇입니까?
Varlor

@Varlor 죄송합니다. 누군가 내 답변을 잘못 편집했습니다. 원래 답변의 편집 기록을 보면 가장 효과적입니다. 이 문제를 해결하기 위해 노력하고 있습니다. (편집 : 방금 들어와 편집을 거부했는데 명백한 파이썬 오류가 발생했습니다. 문제가 해결되었는지 알려주세요.)
Caleb Syring

@CalebSyring 이제 클래스에서 코드를 사용하여 클래스 속성으로 목록을 작성했습니다!
Varlor

2

내가 아는 한 Celery는 대기열에서 대기중인 작업을 검사하기위한 API를 제공하지 않습니다. 이것은 브로커마다 다릅니다. 예를 들어 Redis를 브로커로 사용하는 경우 celery(기본) 대기열 에서 대기중인 작업을 검사하는 것은 다음 과 같이 간단합니다.

  1. 브로커 데이터베이스에 연결
  2. 목록의 목록 항목 celery(예 : LRANGE 명령)

이는 가능한 근로자가 선택하기를 기다리는 작업입니다. 클러스터에 일부 작업이 실행 중일 수 있습니다. 이미 선택한 작업이므로이 목록에 없습니다.


1

대기열에서 작업 수를 얻는 가장 좋은 방법 rabbitmqctl은 여러 번 제안 된대로 사용 하는 것입니다. 선택한 사용자가 명령을 실행할 수 있도록 여기sudo 지침을 따랐습니다 (명령 전에 sudo를 입력해도 상관 없습니다).

또한 jamesc grepcutsnippet을 잡고 하위 프로세스 호출로 마무리했습니다.

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

0

작업 코드를 제어하는 ​​경우 작업이 처음 실행될 때 사소한 재 시도를 트리거 한 다음 확인하여 문제를 해결할 수 있습니다 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

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.