Kerevizdeki bir kuyruktaki görevlerin listesini alma


147

Bir kuyruktaki henüz işlenmemiş görevlerin listesini nasıl alabilirim?


1
RabbitMQ, ama bu listeyi Python içinde almak istiyorum.
bradley.ayers

Yanıtlar:


174

DÜZENLE: Kuyruktaki görevlerin listesini almak için diğer yanıtlara bakın.

Buraya bakmalısın: Kereviz Rehberi - İşçileri Denetleme

Temel olarak bu:

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

Ne istediğine bağlı olarak


9
Bunu denedim, ama gerçekten yavaş (1 sn gibi). İlerlemeyi izlemek için bir kasırga uygulamasında senkronize olarak kullanıyorum, bu yüzden hızlı olmalı.
JulienFr

41
Bu işlem, kuyrukta henüz işlenmemiş görevlerin bir listesini döndürmez.
Ed J

9
i.reserved()Sıraya alınan görevlerin bir listesini almak için kullanın .
Banana

4
İ.reserved () yönteminin etkin görevlerin tam bir listesine sahip olmayacağını bilen var mı? Listede görünmeyen görevlerim var. Ben django-
kerevizdeyim

6
İşçiyi belirtirken ı argüman olarak bir listesini kullanmak zorunda kaldı: inspect(['celery@Flatty']). Üzerinde büyük hız artışı inspect().
Adversus

42

rabbitMQ kullanıyorsanız, bunu terminalde kullanın:

sudo rabbitmqctl list_queues

bekleyen görev sayısı olan kuyrukların listesini yazdırır. Örneğin:

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

sağ sütundaki sayı, kuyruktaki görevlerin sayısıdır. yukarıda, kereviz kuyruğunun 166 bekleyen görevi vardır.


1
Ben sudo ayrıcalıklarına sahip olduğumda bunu biliyorum, ama ayrıcalıklı bir sistem kullanıcısı kontrol edebilmek istiyorum - herhangi bir öneri?
adaçayı

Buna ek olarak boru bu aracılığıyla olabilir grep -e "^celery\s" | cut -f2özü bu 166daha sonra bu sayıyı işlemek istiyorsanız, istatistikler için söylüyorlar.
jamesc

22

Öncelikli görevleri kullanmazsanız, Redis kullanıyorsanız bu oldukça basittir . Görev sayılarını almak için:

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

Ancak, öncelikli görevler yeniden yazmada farklı bir anahtar kullanır , bu nedenle tüm resim biraz daha karmaşıktır. Tam resim, görevin her önceliği için redis sorgulaması yapmanızdır. Python'da (ve Çiçek projesinden), şuna benzer:

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

Gerçek bir görev almak istiyorsanız, aşağıdaki gibi bir şey kullanabilirsiniz:

redis-cli -h HOST -p PORT -n DATABASE_NUMBER lrange QUEUE_NAME 0 -1

Oradan, iade edilen listenin serisini kaldırmanız gerekir. Benim durumumda böyle bir şeyle başarabildim:

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

Serileştirmenin biraz zaman alabileceği konusunda uyarıda bulunun ve çeşitli önceliklerle çalışmak için yukarıdaki komutları ayarlamanız gerekir.


Bunu üretimde kullandıktan sonra , Kereviz tasarımı nedeniyle öncelikli görevleri kullanırsanız başarısız olduğunu öğrendim .
mlissner

1
Öncelikli görevleri yerine getirmek için yukarıdakileri güncelledim. İlerleme!
mlissner

1
Sadece bir şeyleri hecelemek için, DATABASE_NUMBERvarsayılan olarak kullanılan 0ve QUEUE_NAMEis celery, böylece redis-cli -n 0 llen celerysıraya alınmış mesajların sayısını döndürür.
Vineet Bansal

Kereviz için '{{{0}}}{1}{2}'bunun yerine kuyruk adı '{0}{1}{2}'. Bunun dışında, bu mükemmel çalışıyor!
Mart'ta

12

Görevleri arka uçtan almak için bunu kullanın

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
ancak 'işler' sıradaki görevlerin sadece
birkaçını

Size görevlerin adlarını veren ilgili cevap için stackoverflow.com/a/57807913/9843399 adresine bakın .
Caleb Syring

10

Eğer kullanıyorsanız Kereviz + Django görevleriniz da terminalden direkt komutları kullanarak incelemek için basit yolu sanal ortamda ya da kullanan tam yolunu kereviz için:

Doküman : 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

Kullandığınız Ayrıca eğer Kereviz + RabbitMQ yapabilirsiniz kuyruklarının listesi incelemek aşağıdaki komutu kullanarak:

Daha fazla bilgi : https://linux.die.net/man/1/rabbitmqctl

$ sudo rabbitmqctl list_queues

4
Eğer tanımlı bir projeniz varsa, kullanabilirsinizcelery -A my_proj inspect reserved
sashaboulouds

6

Redson için json serileştirmeli bir kopyala yapıştır çözümü:

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 ile çalışır. Sadece değişmeyi unutma yourproject.celery.


1
Turşu serileştiricisini kullanıyorsanız, body =satırı olarak değiştirebilirsiniz body = pickle.loads(base64.b64decode(j['body'])).
Jim Hunziker


3

Bekleyen görevleri almanın tek yolunun, başlattığınız görevlerin bir listesini tutmak ve görevin başlatıldığında listeden kendisini kaldırmasına izin vermektir.

Rabbitmqctl ve list_queues ile kaç görevin beklediğine dair bir genel bakış elde edebilirsiniz, ancak görevlerin kendisini değil: http://www.rabbitmq.com/man/rabbitmqctl.1.man.html

İstediğiniz, işlenmekte olan görevi içeriyor ancak henüz tamamlanmamışsa, görevlerinizin bir listesini tutabilir ve durumlarını kontrol edebilirsiniz:

from tasks import add
result = add.delay(4, 4)

result.ready() # True if finished

Veya Kereviz'in sonuçları CELERY_RESULT_BACKEND ile saklamasına ve hangi görevlerin orada olmadığını kontrol etmesine izin ver.


3

Bu benim uygulamada benim için çalıştı:

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 sıradaki görevlere karşılık gelen dizelerin bir listesi olacaktır.

CELERY_APP_INSTANCE ürününü kendi hesabınızla değiştirmeyi unutmayın.

@Ashish'e cevabı için beni doğru yöne yönlendirdiği için teşekkürler: https://stackoverflow.com/a/19465670/9843399


benim durumumda jobsher zaman sıfır ... herhangi bir fikir?
daveoncode

@daveoncode Bunun yararlı bir şekilde yanıt vermem için yeterli bilginin olduğunu sanmıyorum. Kendi sorunuzu açabilirsiniz. Python bilgi almak istediğinizi belirtirseniz, bu bir kopyası olacağını sanmıyorum. Cevabımı dayandırdığım stackoverflow.com/a/19465670/9843399 adresine geri döneceğim ve önce çalıştığından emin olun.
Caleb Syring

@CalebSyring Bu bana sıraya alınmış görevleri gerçekten gösteren ilk yaklaşım. Çok hoş. Benim için tek sorun liste eki çalışmıyor gibi görünüyor. Herhangi bir fikir nasıl geri arama işlevi listeye yazma yapabilirsiniz?
Varlor

@Varlor Özür dilerim, birisi cevabımda yanlış bir düzenleme yaptı. Sizin için muhtemelen işe yarayacak orijinal yanıt için düzenleme geçmişine bakabilirsiniz. Bunu düzeltmeye çalışıyorum. (DÜZENLEME: Az önce girdim ve belirgin bir python hatası olan düzenlemeyi reddettim. Bu sorunun
çözülüp çözülmediğini

@CalebSyring Artık kodunuzu bir sınıfta kullandım, sınıf özniteliği olarak listenin çalışması!
Varlor

2

Bildiğim kadarıyla Kereviz kuyrukta bekleyen görevleri incelemek için API vermez. Bu, aracıya özgüdür. Bir örnek için aracı olarak Redis'i kullanırsanız, celery(varsayılan) sırada bekleyen görevleri incelemek şu kadar basittir:

  1. aracı veritabanına bağlanma
  2. listedeki öğeleri celerylistele (örnek için LRANGE komutu)

Bunların, mevcut işçiler tarafından seçilmeyi BEKLENEN görevler olduğunu unutmayın. Kümenizde bazı görevler çalışıyor olabilir - bunlar zaten seçildikleri için bu listede olmayacaktır.


1

Bir sıradaki iş sayısını elde etmenin en iyi yolunun rabbitmqctlbirkaç kez önerildiği gibi kullanmak olduğu sonucuna vardım . Herhangi seçilen kullanıcı ile komutu çalıştırmak için izin vermek için sudotalimatları takip I burada (ı komutundan önce sudo yazmaya umursamıyorum olarak profil parçasını düzenlerken atlamak yaptı.)

Ayrıca jamesc grepve cutsnippet'i alıp alt süreç çağrılarına tamamladım.

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

Görevlerin kodunu kontrol ederseniz, bir görevin ilk kez çalıştırıldığında önemsiz bir yeniden denemeyi tetiklemesine ve ardından kontrol etmesine izin vererek sorunu çözebilirsiniz inspect().reserved(). Yeniden deneme görevi sonuç arka ucuna kaydeder ve kereviz bunu görebilir. Yeniden deneme sayısına erişebilmemiz için görevin selfveya contextilk parametre olarak kabul etmesi gerekir .

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

Bu çözelti broker agnostiktir, yani. görevleri saklamak için RabbitMQ veya Redis kullanıp kullanmadığınız konusunda endişelenmenize gerek yoktur.

EDIT: testten sonra bunu sadece kısmi bir çözüm olarak buldum. Ayrılmış boyutu, çalışan için önceden getirme ayarıyla sınırlıdır.


0

İle 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))

Değiştirmeye özen gösterin my_projileyour_proj

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.