सेलेरी में एक कतार में कार्यों की सूची पुनः प्राप्त करें


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 सेकंड)। मैं प्रगति की निगरानी करने के लिए एक बवंडर ऐप में इसे सिंक्रोनाइज़ कर रहा हूं, इसलिए इसे तेज़ होना है।
जूलियनफ्रेंड

41
यह कतार में उन कार्यों की सूची नहीं लौटाएगा जिन्हें अभी तक संसाधित किया जाना है।
एड जे

9
i.reserved()कतारबद्ध कार्यों की सूची प्राप्त करने के लिए उपयोग करें ।
केले

4
क्या किसी ने अनुभव किया है कि i.reserved () में सक्रिय कार्यों की सटीक सूची नहीं होगी? मेरे पास ऐसे कार्य हैं जो सूची में दिखाई नहीं देते हैं। मैं django-celery == 3.1.10 पर हूं
सेपरमैन

6
कार्यकर्ता को निर्दिष्ट करते समय मुझे तर्क के रूप में एक सूची का उपयोग करना पड़ा inspect(['celery@Flatty']):। विशाल गति में सुधार inspect()
एडवर्सस

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
जब मैं सूडो विशेषाधिकार रखता हूं, तो मैं इससे परिचित हूं, लेकिन मैं चाहता हूं कि एक अप्रकाशित, सिस्टम उपयोगकर्ता की जांच करने में सक्षम हो - कोई सुझाव?
ऋषि

इसके अलावा आप इसे grep -e "^celery\s" | cut -f2निकालने के लिए पाइप कर सकते हैं कि 166यदि आप उस नंबर को बाद में संसाधित करना चाहते हैं, तो आंकड़े के लिए कहें।
jamesc

21

यदि आप प्राथमिकता वाले कार्यों का उपयोग नहीं करते हैं, तो यह वास्तव में बहुत आसान है यदि आप रेडिस का उपयोग कर रहे हैं। कार्य को प्राप्त करने के लिए:

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

लेकिन, प्राथमिकता वाले कार्य रेडिस में एक अलग कुंजी का उपयोग करते हैं , इसलिए पूरी तस्वीर थोड़ी अधिक जटिल है। पूरी तस्वीर यह है कि आपको कार्य की प्रत्येक प्राथमिकता के लिए रेडिस को क्वेरी करने की आवश्यकता है। अजगर में (और फूल परियोजना से), ऐसा दिखता है:

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

बस चेतावनी दी जानी चाहिए कि deserialization में एक पल लग सकता है, और आपको विभिन्न प्राथमिकताओं के साथ काम करने के लिए ऊपर दिए गए आदेशों को समायोजित करने की आवश्यकता होगी।


उत्पादन में इसका उपयोग करने के बाद, मैंने सीखा है कि यदि आप प्राथमिकता वाले कार्यों का उपयोग करते हैं , तो अजवाइन के डिजाइन के कारण यह विफल हो जाता है
एमएलसनेर

1
मैंने प्राथमिकता वाले कार्यों को संभालने के लिए ऊपर अद्यतन किया है। प्रगति!
शाम

1
बस चीजों को बाहर निकालने के लिए, DATABASE_NUMBERडिफ़ॉल्ट रूप से उपयोग किया जाता है 0, और QUEUE_NAMEहै celery, इसलिए redis-cli -n 0 llen celeryकतारबद्ध संदेशों की संख्या वापस आ जाएगी।
विनीत बंसल

मेरी अजवाइन के लिए, कतार का नाम '{{{0}}}{1}{2}'इसके बजाय है '{0}{1}{2}'। इसके अलावा, यह पूरी तरह से काम करता है!
14

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
लेकिन 'जॉब्स' कतार में केवल कई कार्य देता है
बिटनिक

संबंधित जवाब के लिए stackoverflow.com/a/57807913/9843399 देखें जो आपको कार्यों का नाम देता है।
बजे कालेब सीरिंग

10

यदि आप अपने वर्चुअल वातावरण में अपने टर्मिनल से सीधे कमांड का उपयोग करते हुए या सेलेरी के लिए एक पूर्ण पथ का उपयोग करते हुए कार्यों का निरीक्षण करने के लिए सेलेरी + Django सरल तरीके का उपयोग कर रहे हैं :

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

रेडिस के लिए एक पेस्ट-पेस्ट समाधान, जोसन क्रमांकन के साथ:

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


1
यदि आप अचार के सिरका का उपयोग कर रहे हैं, तो आप body =लाइन को बदल सकते हैं body = pickle.loads(base64.b64decode(j['body']))
जिम हंजिकर

4

सेलेरी निरीक्षण मॉड्यूल केवल श्रमिकों के दृष्टिकोण से कार्यों के बारे में पता होना प्रतीत होता है। यदि आप उन संदेशों को देखना चाहते हैं जो कतार में हैं (अभी तक श्रमिकों द्वारा खींचे जाने के लिए) तो मैं सुझाव देता हूं कि वे pyrabbit का उपयोग करें , जो कतार से सभी प्रकार की जानकारी प्राप्त करने के लिए rabbitmq http api के साथ इंटरफ़ेस कर सकता है।

एक उदाहरण यहां पाया जा सकता है: अजवाइन के साथ कतार की लंबाई को फिर से प्राप्त करें (RabbitMQ, Django)


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_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 की अदला-बदली करना न भूलें।

यहाँ अपने उत्तर के साथ सही दिशा में इशारा करने के लिए @ashish का धन्यवाद: https://stackoverflow.com/a/19465670/9843399


मेरे मामले jobsमें हमेशा शून्य है ... कोई विचार?
डेवोनकोड

@daveoncode मुझे नहीं लगता कि मदद के लिए प्रतिक्रिया देने के लिए मेरे लिए यह पर्याप्त जानकारी है। आप अपना प्रश्न खोल सकते हैं। मुझे नहीं लगता कि यह इस का एक डुप्लिकेट होगा यदि आप निर्दिष्ट करते हैं कि आप अजगर में जानकारी प्राप्त करना चाहते हैं। मैं वापस stackoverflow.com/a/19465670/9843399 पर जाऊँगा , जो कि मैंने अपना उत्तर बंद कर दिया है, और सुनिश्चित करें कि पहले काम करता है।
कालेब सीरिंग

@CalebSyring यह पहला तरीका है जो वास्तव में मुझे कतारबद्ध कार्यों को दिखाता है। बहुत अच्छा। मेरे लिए एकमात्र समस्या यह है कि सूची परिशिष्ट काम नहीं करता है। कोई भी विचार कि मैं कॉलबैक फ़ंक्शन को सूची में कैसे लिख सकता हूं?
वोरल

@Varlor मुझे खेद है, किसी ने मेरे उत्तर के लिए अनुचित संपादन किया। आप मूल उत्तर के लिए संपादित इतिहास में देख सकते हैं, जो आपके लिए सबसे अधिक संभावना है। मैं इसे ठीक करने पर काम कर रहा हूं। (संपादित करें: मैं अभी गया था और संपादन को अस्वीकार कर दिया था, जिसमें एक स्पष्ट अजगर त्रुटि थी। मुझे बताएं कि क्या इससे आपकी समस्या ठीक हुई या नहीं।)
कालेब सीरिंग जूल

@CalebSyring मैंने अब एक वर्ग में अपने कोड का उपयोग किया, एक वर्ग विशेषता के रूप में सूची में काम करता है!
वर्लोर

2

जहां तक ​​मुझे पता है कि सेलेरी कतार में इंतजार कर रहे कार्यों की जांच के लिए एपीआई नहीं देती है। यह ब्रोकर-विशिष्ट है। यदि आप एक उदाहरण के लिए ब्रोकर के रूप में रेडिस का उपयोग करते हैं, तो उन कार्यों की जांच करना जो celery(डिफ़ॉल्ट) कतार में प्रतीक्षा कर रहे हैं :

  1. ब्रोकर डेटाबेस से कनेक्ट करें
  2. सूची में सूची आइटम celery(उदाहरण के लिए LRANGE कमांड)

ध्यान रखें कि ये कार्य उपलब्ध श्रमिकों द्वारा उठाए जाने वाले कार्य हैं। आपके क्लस्टर में कुछ कार्य चल सकते हैं - वे इस सूची में नहीं होंगे क्योंकि वे पहले ही चुन लिए गए हैं।


1

मैं निष्कर्ष पर आया हूं कि एक कतार में नौकरियों की संख्या प्राप्त करने का सबसे अच्छा तरीका है, rabbitmqctlजैसा कि यहां कई बार सुझाया गया है। किसी भी चुने हुए उपयोगकर्ता को कमांड को चलाने की अनुमति देने के लिए sudoमैंने यहां दिए गए निर्देशों का पालन ​​किया (मैंने कमांड से पहले sudo में टाइप करने का मन नहीं होने पर प्रोफ़ाइल भाग को संपादित करना छोड़ दिया।)

मैंने jamesc grepऔर cutsnippet को भी पकड़ा और इसे सबप्रोसेस कॉल्स में लपेट दिया।

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_projसाथ बदलने के लिए सावधान रहेंyour_proj

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.