Bir kuyruktaki henüz işlenmemiş görevlerin listesini nasıl alabilirim?
Bir kuyruktaki henüz işlenmemiş görevlerin listesini nasıl alabilirim?
Yanıtlar:
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
i.reserved()
Sıraya alınan görevlerin bir listesini almak için kullanın .
inspect(['celery@Flatty'])
. Üzerinde büyük hız artışı inspect()
.
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.
grep -e "^celery\s" | cut -f2
özü bu 166
daha sonra bu sayıyı işlemek istiyorsanız, istatistikler için söylüyorlar.
Ö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.
DATABASE_NUMBER
varsayılan olarak kullanılan 0
ve QUEUE_NAME
is celery
, böylece redis-cli -n 0 llen celery
sıraya alınmış mesajların sayısını döndürür.
'{{{0}}}{1}{2}'
bunun yerine kuyruk adı '{0}{1}{2}'
. Bunun dışında, bu mükemmel çalışıyor!
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)
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
celery -A my_proj inspect reserved
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
.
body =
satırı olarak değiştirebilirsiniz body = pickle.loads(base64.b64decode(j['body']))
.
Kereviz denetleme modülü, sadece işçilerin bakış açısından görevlerin farkında gibi görünmektedir. Sıradaki mesajları görüntülemek istiyorsanız (henüz işçiler tarafından alınmamış) pyrabbit'i kullanmanızı öneririm her türlü bilgiyi almak için rabbitmq http api ile arayüz oluşturabilen .
Bir örnek burada bulunabilir: Kereviz ile kuyruk uzunluğunu alma (RabbitMQ, Django)
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.
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
jobs
her zaman sıfır ... herhangi bir fikir?
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:
celery
listele (ö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.
Bir sıradaki iş sayısını elde etmenin en iyi yolunun rabbitmqctl
birkaç 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 sudo
talimatları takip I burada (ı komutundan önce sudo yazmaya umursamıyorum olarak profil parçasını düzenlerken atlamak yaptı.)
Ayrıca jamesc grep
ve cut
snippet'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]))
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 self
veya context
ilk 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.
İ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_proj
ileyour_proj