मैं एक कतार में उन कार्यों की सूची कैसे प्राप्त कर सकता हूं जिन्हें अभी तक संसाधित नहीं किया गया है?
मैं एक कतार में उन कार्यों की सूची कैसे प्राप्त कर सकता हूं जिन्हें अभी तक संसाधित नहीं किया गया है?
जवाबों:
संपादित करें: कतार में कार्यों की सूची प्राप्त करने के लिए अन्य उत्तर देखें।
आपको यहां देखना चाहिए: सेलेरी गाइड - निरीक्षण कार्यकर्ता
मूल रूप से यह:
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()
आप जो चाहते हैं उसके आधार पर
i.reserved()
कतारबद्ध कार्यों की सूची प्राप्त करने के लिए उपयोग करें ।
inspect(['celery@Flatty'])
:। विशाल गति में सुधार inspect()
।
अगर आप 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 लंबित कार्य हैं।
grep -e "^celery\s" | cut -f2
निकालने के लिए पाइप कर सकते हैं कि 166
यदि आप उस नंबर को बाद में संसाधित करना चाहते हैं, तो आंकड़े के लिए कहें।
यदि आप प्राथमिकता वाले कार्यों का उपयोग नहीं करते हैं, तो यह वास्तव में बहुत आसान है यदि आप रेडिस का उपयोग कर रहे हैं। कार्य को प्राप्त करने के लिए:
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 में एक पल लग सकता है, और आपको विभिन्न प्राथमिकताओं के साथ काम करने के लिए ऊपर दिए गए आदेशों को समायोजित करने की आवश्यकता होगी।
DATABASE_NUMBER
डिफ़ॉल्ट रूप से उपयोग किया जाता है 0
, और QUEUE_NAME
है celery
, इसलिए redis-cli -n 0 llen celery
कतारबद्ध संदेशों की संख्या वापस आ जाएगी।
'{{{0}}}{1}{2}'
इसके बजाय है '{0}{1}{2}'
। इसके अलावा, यह पूरी तरह से काम करता है!
बैकएंड से कार्यों को पुनः प्राप्त करने के लिए, इसका उपयोग करें
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)
यदि आप अपने वर्चुअल वातावरण में अपने टर्मिनल से सीधे कमांड का उपयोग करते हुए या सेलेरी के लिए एक पूर्ण पथ का उपयोग करते हुए कार्यों का निरीक्षण करने के लिए सेलेरी + 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
celery -A my_proj inspect reserved
रेडिस के लिए एक पेस्ट-पेस्ट समाधान, जोसन क्रमांकन के साथ:
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
।
body =
लाइन को बदल सकते हैं body = pickle.loads(base64.b64decode(j['body']))
।
सेलेरी निरीक्षण मॉड्यूल केवल श्रमिकों के दृष्टिकोण से कार्यों के बारे में पता होना प्रतीत होता है। यदि आप उन संदेशों को देखना चाहते हैं जो कतार में हैं (अभी तक श्रमिकों द्वारा खींचे जाने के लिए) तो मैं सुझाव देता हूं कि वे pyrabbit का उपयोग करें , जो कतार से सभी प्रकार की जानकारी प्राप्त करने के लिए rabbitmq http api के साथ इंटरफ़ेस कर सकता है।
एक उदाहरण यहां पाया जा सकता है: अजवाइन के साथ कतार की लंबाई को फिर से प्राप्त करें (RabbitMQ, Django)
मुझे लगता है कि जिन कार्यों की प्रतीक्षा की जा रही है उनका एकमात्र तरीका आपके द्वारा शुरू किए गए कार्यों की एक सूची रखना है और कार्य को शुरू होने पर सूची से खुद को हटाने दें।
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 परिणामों को संग्रहीत करने दें और जांचें कि आपके कौन से कार्य इसमें नहीं हैं।
यह मेरे लिए मेरे आवेदन में काम आया:
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
में हमेशा शून्य है ... कोई विचार?
जहां तक मुझे पता है कि सेलेरी कतार में इंतजार कर रहे कार्यों की जांच के लिए एपीआई नहीं देती है। यह ब्रोकर-विशिष्ट है। यदि आप एक उदाहरण के लिए ब्रोकर के रूप में रेडिस का उपयोग करते हैं, तो उन कार्यों की जांच करना जो celery
(डिफ़ॉल्ट) कतार में प्रतीक्षा कर रहे हैं :
celery
(उदाहरण के लिए LRANGE कमांड)ध्यान रखें कि ये कार्य उपलब्ध श्रमिकों द्वारा उठाए जाने वाले कार्य हैं। आपके क्लस्टर में कुछ कार्य चल सकते हैं - वे इस सूची में नहीं होंगे क्योंकि वे पहले ही चुन लिए गए हैं।
मैं निष्कर्ष पर आया हूं कि एक कतार में नौकरियों की संख्या प्राप्त करने का सबसे अच्छा तरीका है, rabbitmqctl
जैसा कि यहां कई बार सुझाया गया है। किसी भी चुने हुए उपयोगकर्ता को कमांड को चलाने की अनुमति देने के लिए sudo
मैंने यहां दिए गए निर्देशों का पालन किया (मैंने कमांड से पहले sudo में टाइप करने का मन नहीं होने पर प्रोफ़ाइल भाग को संपादित करना छोड़ दिया।)
मैंने jamesc grep
और cut
snippet को भी पकड़ा और इसे सबप्रोसेस कॉल्स में लपेट दिया।
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]))
यदि आप कार्यों के कोड को नियंत्रित करते हैं तो आप समस्या को हल करने का काम कर सकते हैं, जिससे कार्य को पहली बार निष्पादित करने पर तुच्छ रिट्रीव करने की अनुमति मिलती है inspect().reserved()
। रिट्रीट परिणाम बैकएंड के साथ कार्य को पंजीकृत करता है, और अजवाइन वह देख सकता है। कार्य को पहले पैरामीटर के रूप में स्वीकार करना चाहिए self
या करना चाहिए context
ताकि हम पुन: प्रयास करें।
@task(bind=True)
def mytask(self):
if self.request.retries == 0:
raise self.retry(exc=MyTrivialError(), countdown=1)
...
यह समाधान है दलाल अज्ञेय, यानी। आपको इस बात की चिंता करने की आवश्यकता नहीं है कि आप कार्यों को संग्रहीत करने के लिए RabbitMQ या Redis का उपयोग कर रहे हैं या नहीं।
संपादित करें: परीक्षण के बाद मैंने पाया है कि यह केवल एक आंशिक समाधान है। आरक्षित का आकार कार्यकर्ता के लिए प्रीफैच सेटिंग तक सीमित है।
के साथ 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