Как проверить статус задачи в Celery?


95

Как проверить, выполняется ли задача в сельдерее (в частности, я использую celery-django)?

Я прочитал документацию и погуглил, но не вижу вызова вроде:

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, чтобы отслеживать работу в будущем.
Грегор

В отличие от @ Marcin, в этом ответе не используется статический метод Task.AsyncResult () в качестве фабрики AsyncResult, который повторно использует конфигурацию серверной части, в противном случае возникает ошибка при попытке получить результат.
ArnauOrriols

2
@Chris Противоречие с кодом @gregor связано с созданием экземпляра 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объекта из идентификатора задачи - это способ, рекомендованный в FAQ для получения статуса задачи, когда единственное, что у вас есть, - это идентификатор задачи.

Однако, начиная с Celery 3.x, есть серьезные предостережения, которые могут укусить людей, если они не обратят на них внимание. Это действительно зависит от конкретного сценария использования.

По умолчанию Celery не записывает «запущенное» состояние.

Чтобы 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на True, то состояние будет STARTED.

Состояние PENDINGозначает «я не знаю».

С AsyncResultсостоянием PENDINGне означает ничего, кроме того, что Celery не знает статус задачи. Это могло быть по любому количеству причин.

Во-первых, AsyncResultмогут быть созданы с недопустимыми идентификаторами задач. Такие «задачи» будут считаться отложенными для Celery:

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

Итак, никто не будет скармливать явно недействительные идентификаторы AsyncResult. Достаточно справедливо, но он также имеет эффект, AsyncResultкоторый также учитывает задачу, которая успешно выполнена, но о которой Celery забыл PENDING. Опять же, в некоторых сценариях использования это может быть проблемой. Частично проблема зависит от того, как Celery настроен для хранения результатов задач, потому что это зависит от доступности «надгробий» в серверной части результатов. («Надгробия» - это термин, который используется в документации по сельдерею для фрагментов данных, которые фиксируют, как закончилась задача.) Использование AsyncResultвообще не будет работать, если оно task_ignore_resultесть True. Более неприятная проблема заключается в том, что Celery по умолчанию истекает срок действия надгробий. Вresult_expiresнастройка по умолчанию установлена ​​на 24 часа. Итак, если вы запускаете задачу и записываете идентификатор в долгосрочное хранилище, и более 24 часов спустя вы создаете AsyncResultс ним задачу, статус будет PENDING.

Все «настоящие задачи» запускаются в PENDINGштате. Таким образом, PENDINGвыполнение задачи может означать, что задача была запрошена, но никогда не продвинулась дальше (по какой-либо причине). Или это может означать, что задача выполнена, но Celery забыл о своем состоянии.

Ой! AsyncResultу меня не сработает. Что еще я могу сделать?

Я предпочитаю отслеживать цели, а не сами задачи . Я храню некоторую информацию о задачах, но это второстепенно по отношению к отслеживанию целей. Цели хранятся в хранилище независимо от сельдерея. Когда запрос должен выполнить вычисление, зависит от достигнутой цели, он проверяет, была ли цель уже достигнута, если да, то он использует эту кешированную цель, в противном случае запускает задачу, которая повлияет на цель, и отправляет ее в клиент, сделавший HTTP-запрос, является ответом, который указывает, что он должен дождаться результата.


Имена переменных и гиперссылки выше предназначены для Celery 4.x. В 3.x соответствующие переменные и гиперссылки: CELERY_TRACK_STARTED, CELERY_IGNORE_RESULT, CELERY_TASK_RESULT_EXPIRES.


Так что, если я хочу проверить результат позже (может быть, даже в рамках другого процесса), мне лучше с моей собственной реализацией? Сохранение результата в базе данных вручную?
Франклин Ю

Да, я бы отделил отслеживание «цели» от отслеживания «задач». Я написал «выполнить вычисление, которое зависит от какой-то цели». Обычно «цель» также является вычислением. Например, если я хочу показать статью X пользователю, я должен преобразовать ее из XML в HTML, но перед этим я должен разрешить все библиографические ссылки. (X подобен журнальной статье.) Я проверяю, существует ли цель «статья X со всеми разрешенными библиографическими ссылками», и использую ее вместо того, чтобы пытаться проверить состояние задачи Celery, которая могла бы вычислить желаемую цель.
Луи

И информация «статья X со всеми разрешенными библиографическими ссылками» сохраняется в кэше памяти и хранится в базе данных eXist-db.
Луи

63

Каждый Taskобъект имеет .requestсвойство, которое содержит его AsyncRequestобъект. Соответственно, следующая строка показывает состояние Задачи task:

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

2
Есть ли способ сохранить процент выполнения задачи?
Патрик

5
Когда я это делаю, я получаю постоянно PENDING AsyncResult, даже если я достаточно долго жду завершения задачи. Есть ли способ заставить это видеть изменения состояния? Я считаю, что мой бэкэнд настроен, и я попытался установить CELERY_TRACK_STARTED = True, но безрезультатно.
dstromberg 09

1
@dstromberg К сожалению, прошло 4 года с тех пор, как это было проблемой для меня, поэтому я не могу помочь. Вам почти наверняка нужно настроить сельдерей для отслеживания статуса.
Marcin

В дополнение к наблюдениям @dstromberg, просто для подтверждения, я взял задачу с сельдереем, которая, как я точно знал, успешно завершилась, и проверил ее stateсвойства, она все равно вернулась PENDING. Это не кажется надежным способом отслеживать состояние задач сельдерея с терминала. Кроме того, у меня работает Celery Flower (инструмент мониторинга сельдерея), по какой-то причине он не отображал задачи, которые я искал, в списке задач, которые он выполнил. Возможно, мне придется заглянуть в настройки цветов, чтобы увидеть, есть ли что-нибудь, что говорит показывать только до определенных часов в прошлом.
Deep

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
Совершенно не нужно создавать собственный идентификатор задачи и передавать его apply_async. Возвращаемый объект apply_async - это AsyncResultобъект, у которого есть идентификатор задачи, созданной Celery.
Луи

1
Поправьте меня, если я ошибаюсь, но разве иногда не полезно сгенерировать UUID на основе некоторых входных данных, чтобы все вызовы, получающие одинаковые входные данные, получали один и тот же UUID? IOW, может быть, иногда полезно указать свой task_id.
dstromberg 09

1
@dstromberg Вопрос, который задает OP, - «как мне проверить статус задачи», а ответ здесь гласит: «Если вы пытаетесь получить task_id ...». Ни проверки статуса задачи, ни task_idтребования, чтобы вы сами сгенерировали идентификатор задачи. В своем комментарии вы представили причину, которая выходит за рамки «как мне проверить статус задачи» и «Если вы пытаетесь получить task_id ...` Отлично, если у вас есть такая потребность, но это не так здесь. (Кроме того, использование uuid()для генерации идентификатора задачи не делает абсолютно ничего, кроме того, что делает
Луи,

Я согласен с тем, что OP специально не спрашивал, как получить предсказуемые идентификаторы задач, но ответ на вопрос OP в настоящее время - «отслеживать идентификатор задачи и делать x». Мне кажется, что отслеживание идентификатора задачи нецелесообразно в самых разных ситуациях, поэтому ответ на самом деле может быть неудовлетворительным. Этот ответ помогает мне решить мой вариант использования (если я смогу преодолеть другие отмеченные ограничения) по той же причине, по которой указывает @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. Если задача Celery уже находится в состоянии FAILURE, она выдаст исключение:

raised unexpected: KeyError('exc_type',)


0

для простых задач мы можем использовать http://flower.readthedocs.io/en/latest/screenshots.html и http://policystat.github.io/jobtastic/ для мониторинга.

а для сложных задач, скажем, задача, связанная с множеством других модулей. Мы рекомендуем вручную записывать ход выполнения и сообщения по конкретной задаче.


0

Я нашел полезную информацию в

Руководство для работников проекта сельдерея, инспектирующие рабочих

В моем случае я проверяю, работает ли Celery.

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

Вы можете поиграть с inspect, чтобы понять свои потребности.


0
  • Сначала , в приложении для сельдерея :

vi my_celery_apps / app1.py

app = Celery(worker_name)
  • а затем перейдите в файл задачи , импортируйте приложение из вашего модуля приложения celery.

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
Пожалуйста, не публикуйте только код в качестве ответа, но также объясните, что делает ваш код и как он решает проблему вопроса. Ответы с объяснением обычно более полезны и качественнее, и с большей вероятностью получат положительные отзывы.
Марк Роттевил,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.