จะตรวจสอบสถานะงานในคื่นฉ่ายได้อย่างไร?


95

เราจะตรวจสอบได้อย่างไรว่างานกำลังทำงานในคื่นฉ่าย (โดยเฉพาะฉันใช้คื่นฉ่าย django)

ฉันได้อ่านเอกสารและ googled แต่ฉันไม่เห็นการโทรเช่น:

my_example_task.state() == RUNNING

กรณีการใช้งานของฉันคือฉันมีบริการภายนอก (java) สำหรับการแปลงรหัส เมื่อฉันส่งเอกสารที่จะแปลงรหัสฉันต้องการตรวจสอบว่างานที่เรียกใช้บริการนั้นกำลังทำงานอยู่หรือไม่และหากไม่เป็นเช่นนั้นให้เริ่มต้นใหม่

ฉันใช้เวอร์ชันเสถียรปัจจุบัน - 2.4 ฉันเชื่อ

คำตอบ:


98

ส่งคืน task_id (ซึ่งได้รับจาก. delay ()) และถามอินสแตนซ์ขึ้นฉ่ายในภายหลังเกี่ยวกับสถานะ:

x = method.delay(1,2)
print x.task_id

เมื่อถามให้รับ AsyncResult ใหม่โดยใช้ task_id นี้:

from celery.result import AsyncResult
res = AsyncResult("your-task-id")
res.ready()

11
ขอบคุณ แต่ถ้าฉันไม่สามารถเข้าถึงได้xล่ะ?
Marcin

4
คุณจัดงานของคุณเป็นผักชีฝรั่งที่ไหน? คุณต้องส่งคืน task_id เพื่อติดตามงานในอนาคต
Gregor

ซึ่งแตกต่างจาก @ Marcin คำตอบนี้ไม่ได้ใช้วิธีการแบบคงที่ Task AsyncResult () เป็นโรงงานของ AsyncResult ซึ่งนำการกำหนดค่าแบ็กเอนด์กลับมาใช้ใหม่อย่างเป็นประโยชน์มิฉะนั้นจะเกิดข้อผิดพลาดเมื่อพยายามรับผลลัพธ์
ArnauOrriols

2
@ Chris ความขัดแย้งด้วยรหัส @gregor อยู่ใน instantiation async_resultของ ในกรณีการใช้งานของคุณคุณมีอินสแตนซ์อยู่แล้วคุณก็พร้อมใช้งาน แต่สิ่งที่เกิดขึ้นถ้าคุณมีเพียงรหัสงานและจำเป็นที่จะต้องยกตัวอย่างasync_resultอินสแตนซ์ที่จะสามารถที่จะเรียกasync_result.get()? นี่คือตัวอย่างของAsyncResultชั้น แต่คุณไม่สามารถใช้คลาสดิบcelery.result.AsyncResult, app.task()คุณต้องได้รับจากการทำงานระดับห่อโดย ในกรณีที่คุณจะทำasync_result = run_instance.AsyncResult('task-id')
ArnauOrriols

1
but you cannot use the raw class celery.result.AsyncResult, you need to get the class from the function wrapped by app.task(). - ฉันคิดว่านี่เป็นวิธีที่ควรใช้จริงๆ อ่านโค้ด: github.com/celery/celery/blob/…
nevelis

74

การสร้างAsyncResultอ็อบเจกต์จาก id งานเป็นวิธีที่แนะนำในFAQเพื่อรับสถานะงานเมื่อสิ่งเดียวที่คุณมีคือ id งาน

อย่างไรก็ตามสำหรับคื่นฉ่าย 3.x มีข้อแม้ที่สำคัญที่สามารถกัดคนได้หากพวกเขาไม่ใส่ใจกับพวกเขา มันขึ้นอยู่กับสถานการณ์การใช้งานที่เฉพาะเจาะจง

ตามค่าเริ่มต้น Celery จะไม่บันทึกสถานะ "กำลังทำงาน"

เพื่อให้คื่นฉ่ายจะบันทึกว่างานกำลังทำงานคุณต้องตั้งค่าการtask_track_started Trueนี่คืองานง่ายๆที่ทดสอบสิ่งนี้:

@app.task(bind=True)
def test(self):
    print self.AsyncResult(self.request.id).state

เมื่อtask_track_startedใดFalseซึ่งเป็นค่าเริ่มต้นการแสดงสถานะคือPENDINGแม้ว่างานจะเริ่มแล้ว หากคุณตั้งtask_track_startedไปแล้วรัฐจะTrueSTARTED

รัฐPENDINGแปลว่า "ไม่รู้"

AsyncResultกับรัฐPENDINGได้ทำอะไรเลยไม่ได้หมายความว่ามากกว่านั้นคื่นฉ่ายไม่ทราบสถานะของงาน อาจเป็นเพราะสาเหตุหลายประการ

ประการหนึ่งAsyncResultสามารถสร้างด้วยรหัสงานที่ไม่ถูกต้อง "งาน" ดังกล่าวจะถือว่าขึ้นฉ่าย:

>>> task.AsyncResult("invalid").status
'PENDING'

ตกลงดังนั้นไม่มีใครจะไปกินอาหารอย่างเห็นได้ชัดAsyncResultไม่ถูกต้องรหัสไป พอเป็นธรรม แต่ก็ยังมีผลกระทบที่AsyncResultจะพิจารณางานที่มีการทำงานประสบความสำเร็จ PENDINGแต่ที่คื่นฉ่ายได้ลืมความเป็นอยู่ อีกครั้งในสถานการณ์การใช้งานบางกรณีอาจเป็นปัญหาได้ ส่วนหนึ่งของปัญหาขึ้นอยู่กับวิธีกำหนดค่า Celery ให้เก็บผลลัพธ์ของงานไว้เนื่องจากขึ้นอยู่กับความพร้อมของ "tombstones" ในแบ็กเอนด์ของผลลัพธ์ ( "Tombstones" คือการใช้คำในเอกสารคื่นฉ่ายสำหรับชิ้นข้อมูลที่บันทึกว่างานสิ้นสุด.) การใช้AsyncResultจะไม่ทำงานเลยถ้ามีtask_ignore_result Trueปัญหาที่น่าวิตกกว่าคือคื่นฉ่ายจะหมดอายุหลุมฝังศพตามค่าเริ่มต้น result_expiresการตั้งค่าโดยค่าเริ่มต้นตั้งไว้ที่ 24 ชั่วโมง ดังนั้นถ้าคุณเปิดงานและบันทึกรหัสในการจัดเก็บระยะยาว, และอื่น ๆ อีก 24 ชั่วโมงต่อมาคุณสร้างกับมันสถานะจะเป็นAsyncResultPENDING

"งานจริง" ทั้งหมดเริ่มต้นในPENDINGสถานะ ดังนั้นการPENDINGทำงานอาจหมายความว่ามีการร้องของาน ​​แต่ไม่ก้าวหน้าไปกว่านี้ (ไม่ว่าด้วยเหตุผลใดก็ตาม) หรืออาจหมายถึงงานกำลังดำเนินไป แต่คื่นช่ายลืมสถานะของมัน

อุ๊ย! AsyncResultจะไม่ทำงานสำหรับฉัน ฉันจะทำอะไรได้อีก?

ฉันชอบที่จะติดตามเป้าหมายกว่าติดตามของงานตัวเอง ฉันเก็บข้อมูลงานบางอย่างไว้ แต่เป็นเรื่องรองในการติดตามเป้าหมาย เป้าหมายจะถูกเก็บไว้ในที่จัดเก็บโดยไม่ขึ้นกับขึ้นฉ่าย เมื่อคำขอจำเป็นต้องทำการคำนวณขึ้นอยู่กับเป้าหมายบางอย่างที่บรรลุเป้าหมายแล้วจะตรวจสอบว่าบรรลุเป้าหมายแล้วหรือไม่หากใช่จากนั้นจะใช้เป้าหมายที่เก็บไว้นี้มิฉะนั้นจะเริ่มงานที่จะส่งผลต่อเป้าหมายและส่งไปยัง ไคลเอ็นต์ที่ทำการร้องขอ HTTP เป็นการตอบสนองที่บ่งชี้ว่าควรรอผลลัพธ์


ชื่อตัวแปรและการเชื่อมโยงหลายมิติด้านบนใช้สำหรับ Celery 4.x. ใน 3.x CELERY_TRACK_STARTEDตัวแปรที่สอดคล้องและเชื่อมโยงหลายมิติคือ: CELERY_IGNORE_RESULT, CELERY_TASK_RESULT_EXPIRES,


ดังนั้นหากฉันต้องการตรวจสอบผลลัพธ์ในภายหลัง (อาจจะอยู่ในกระบวนการอื่น) ฉันควรนำไปใช้ด้วยตัวเอง การจัดเก็บผลลัพธ์ลงในฐานข้อมูลด้วยตนเอง?
Franklin Yu

ใช่ฉันแยกการติดตาม "เป้าหมาย" ออกจากการติดตาม "งาน" ฉันเขียนว่า "ทำการคำนวณที่ขึ้นอยู่กับเป้าหมายบางอย่าง" โดยปกติแล้ว "เป้าหมาย" ยังเป็นการคำนวณ ตัวอย่างเช่นหากฉันต้องการแสดงบทความ X ให้กับผู้ใช้ฉันต้องแปลงจาก XML เป็น HTML แต่ก่อนหน้านั้นฉันต้องแก้ไขการอ้างอิงบรรณานุกรมทั้งหมด (X เปรียบเสมือนบทความในวารสาร) ฉันตรวจสอบว่าเป้าหมาย "บทความ X ที่มีการอ้างอิงทางบรรณานุกรมทั้งหมดได้รับการแก้ไขแล้วหรือไม่" และใช้สิ่งนั้นแทนที่จะพยายามตรวจสอบสถานะงานของงานคื่นฉ่ายที่จะคำนวณเป้าหมายที่ฉันต้องการ
Louis

และข้อมูล "บทความ X พร้อมการอ้างอิงทางบรรณานุกรมทั้งหมดได้รับการแก้ไขแล้ว" จะถูกเก็บไว้ในแคชหน่วยความจำและเก็บไว้ในฐานข้อมูล eXist-db
Louis

63

ทุกTaskวัตถุมี.requestคุณสมบัติซึ่งประกอบด้วยAsyncRequestวัตถุ ดังนั้นบรรทัดต่อไปนี้จะให้สถานะของงานtask:

task.AsyncResult(task.request.id).state

2
มีวิธีจัดเก็บเปอร์เซ็นต์ความคืบหน้าของงานหรือไม่?
patrick

5
เมื่อฉันทำสิ่งนี้ฉันจะได้รับ AsyncResult ที่รออยู่อย่างถาวรแม้ว่าฉันจะรอนานพอที่งานจะเสร็จ มีวิธีทำให้เห็นการเปลี่ยนแปลงสถานะนี้หรือไม่? ฉันเชื่อว่าแบ็กเอนด์ของฉันได้รับการกำหนดค่าแล้วและฉันลองตั้งค่า CELERY_TRACK_STARTED = True เพื่อไม่มีประโยชน์
dstromberg

1
@dstromberg น่าเสียดายที่มันเป็นปัญหาสำหรับฉันมา 4 ปีแล้วดังนั้นฉันจึงช่วยไม่ได้ คุณแทบจะต้องกำหนดค่าคื่นฉ่ายเพื่อติดตามสถานะ
Marcin

เพิ่มต่อไป @ dstromberg ของการสังเกตเพียงเพื่อประโยชน์ในการยืนยันให้ผมหยิบขึ้นมาเป็นงานคื่นฉ่ายที่ฉันรู้เพื่อตรวจสอบว่าได้ประสบความสำเร็จและประสบความสำเร็จในการตรวจสอบของสถานที่ให้บริการก็ยังคงกลับมาstate PENDINGดูเหมือนจะไม่ใช่วิธีที่เชื่อถือได้ในการติดตามสถานะของงานขึ้นฉ่ายจากเทอร์มินัล นอกจากนี้ฉันมี Celery Flower (Celery Monitoring Tool) ทำงานอยู่ด้วยเหตุผลบางอย่างมันไม่แสดงงานที่ฉันกำลังมองหาในรายการงานที่ได้ดำเนินการ ฉันอาจต้องตรวจสอบการตั้งค่าดอกไม้เพื่อดูว่ามีอะไรที่ระบุว่าแสดงไม่เกินหนึ่งชั่วโมงในอดีตหรือไม่
ลึก

16

นอกจากนี้คุณยังสามารถสร้างสถานะที่กำหนดเองและอัปเดตค่าตามการเรียกใช้งาน ตัวอย่างนี้มาจากเอกสาร:

@app.task(bind=True)
def upload_files(self, filenames):
    for i, file in enumerate(filenames):
        if not self.request.called_directly:
            self.update_state(state='PROGRESS',
                meta={'current': i, 'total': len(filenames)})

http://celery.readthedocs.org/en/latest/userguide/tasks.html#custom-states


11

คำถามเก่า แต่ฉันเพิ่งพบปัญหานี้

หากคุณพยายามรับ task_id คุณสามารถทำได้ดังนี้:

import celery
from celery_app import add
from celery import uuid

task_id = uuid()
result = add.apply_async((2, 2), task_id=task_id)

ตอนนี้คุณรู้แล้วว่า task_id คืออะไรและสามารถใช้เพื่อรับ AsyncResult:

# grab the AsyncResult 
result = celery.result.AsyncResult(task_id)

# print the task id
print result.task_id
09dad9cf-c9fa-4aee-933f-ff54dae39bdf

# print the AsyncResult's status
print result.status
SUCCESS

# print the result returned 
print result.result
4

4
มีอย่างไม่มีต้องสร้าง ID apply_asyncงานของคุณเองและผ่านมันไป วัตถุที่ส่งคืนโดยapply_async เป็นAsyncResultวัตถุซึ่งมี id ของงานที่ขึ้นฉ่ายสร้างขึ้น
Louis

1
แก้ไขฉันถ้าฉันผิด แต่บางครั้งก็ไม่มีประโยชน์ในการสร้าง UUID ตามอินพุตบางอย่างเพื่อให้การโทรทั้งหมดที่ได้รับอินพุตเดียวกันได้รับ UUID เดียวกัน IOW บางทีการระบุ task_id ของคุณก็มีประโยชน์
dstromberg

1
@dstromberg คำถามที่ OP ถามคือ "ฉันจะตรวจสอบสถานะงานได้อย่างไร" และคำตอบจะระบุว่า "หากคุณกำลังพยายามรับ task_id ... " ไม่ต้องตรวจสอบสถานะงานไม่ได้รับความtask_idต้องการให้คุณสร้างรหัสงานด้วยตัวเอง ในความคิดเห็นของคุณคุณได้จินตนาการถึงเหตุผลที่เหนือกว่า "ฉันจะตรวจสอบสถานะงานได้อย่างไร" และ "หากคุณกำลังพยายามรับ task_id ... ` เยี่ยมมากถ้าคุณมีความต้องการนั้น แต่ไม่เป็นเช่นนั้น ที่นี่ (นอกจากนี้การใช้uuid()เพื่อสร้างรหัสงานไม่ได้ทำอะไรเลยนอกจากขึ้นฉ่ายเป็นค่าเริ่มต้น)
หลุยส์

ฉันยอมรับว่า OP ไม่ได้ถามถึงวิธีรับ ID งานที่คาดเดาได้โดยเฉพาะ แต่ขณะนี้คำตอบสำหรับคำถามของ OP คือ "ติดตาม ID งานและทำ x" สำหรับฉันแล้วดูเหมือนว่าการติดตาม ID งานนั้นไม่สามารถทำได้ในหลาย ๆ สถานการณ์ดังนั้นคำตอบนั้นอาจไม่เป็นที่น่าพอใจ คำตอบนี้ช่วยฉันแก้ปัญหาการใช้งานของฉัน (ถ้าฉันสามารถเอาชนะข้อ จำกัด อื่น ๆ ที่ระบุไว้ได้) ด้วยเหตุผลเดียวกันที่ @dstromberg ชี้ให้เห็น - ไม่ว่าจะมีแรงจูงใจด้วยเหตุผลนั้นหรือไม่ก็ตาม
claytond


1

คำตอบของปี 2020:

#### tasks.py
@celery.task()
def mytask(arg1):
    print(arg1)

#### blueprint.py
@bp.route("/args/arg1=<arg1>")
def sleeper(arg1):
    process = mytask.apply_async(args=(arg1,)) #mytask.delay(arg1)
    state = process.state
    return f"Thanks for your patience, your job {process.task_id} \
             is being processed. Status {state}"

0

ลอง:

task.AsyncResult(task.request.id).state

สิ่งนี้จะให้สถานะงานขึ้นฉ่าย หาก Celery Task อยู่ในสถานะFAILUREอยู่แล้วจะทำให้เกิด Exception:

raised unexpected: KeyError('exc_type',)


0

สำหรับงานง่ายๆเราสามารถใช้http://flower.readthedocs.io/en/latest/screenshots.htmlและhttp://policystat.github.io/jobtastic/เพื่อตรวจสอบ

และสำหรับงานที่ซับซ้อนให้พูดว่างานที่เกี่ยวข้องกับโมดูลอื่น ๆ มากมาย เราขอแนะนำให้บันทึกความคืบหน้าและข้อความด้วยตนเองในหน่วยงานเฉพาะ


0

ฉันพบข้อมูลที่เป็นประโยชน์ในไฟล์

คู่มือคนงานโครงการคื่นฉ่ายตรวจคนงาน

สำหรับกรณีของฉันฉันกำลังตรวจสอบว่าขึ้นฉ่ายทำงานอยู่หรือไม่

inspect_workers = task.app.control.inspect()
if inspect_workers.registered() is None:
    state = 'FAILURE'
else:
    state = str(task.state) 

คุณสามารถเล่นกับการตรวจสอบเพื่อตอบสนองความต้องการของคุณ


0
  • ครั้งแรก, ในแอปขึ้นฉ่ายของคุณ:

vi my_celery_apps / app1.py

app = Celery(worker_name)
  • และถัดไปเปลี่ยนเป็นไฟล์งาน, นำเข้าแอพจากโมดูลแอพขึ้นฉ่ายของคุณ

vi งาน / task1.py

from my_celery_apps.app1 import app

app.AsyncResult(taskid)

try:
   if task.state.lower() != "success":
        return
except:
    """ do something """


-1

นอกเหนือจากข้างต้นวิธีการแบบเป็นโปรแกรมโดยใช้สถานะงานดอกไม้สามารถมองเห็นได้ง่าย

การตรวจสอบตามเวลาจริงโดยใช้ Celery Events Flower เป็นเครื่องมือบนเว็บสำหรับการตรวจสอบและจัดการกลุ่มคื่นฉ่าย

  1. ความคืบหน้าและประวัติของงาน
  2. ความสามารถในการแสดงรายละเอียดงาน (อาร์กิวเมนต์เวลาเริ่มต้นรันไทม์และอื่น ๆ )
  3. กราฟและสถิติ

เอกสารอย่างเป็นทางการ: ดอกไม้ - เครื่องมือตรวจสอบขึ้นฉ่าย

การติดตั้ง:

$ pip install flower

การใช้งาน:

http://localhost:5555

-1
res = method.delay()
    
print(f"id={res.id}, state={res.state}, status={res.status} ")

print(res.get())

2
โปรดอย่าโพสต์โค้ดเพื่อเป็นคำตอบเท่านั้น แต่ให้อธิบายด้วยว่าโค้ดของคุณใช้ทำอะไรและแก้ไขปัญหาของคำถามได้อย่างไร คำตอบพร้อมคำอธิบายมักจะมีประโยชน์มากกว่าและมีคุณภาพดีกว่าและมีแนวโน้มที่จะดึงดูดการโหวตมากขึ้น
Mark Rotteveel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.