如何检查一项任务是否在celery中运行(特别是我正在使用celery-django)?
我已经阅读了文档,并且已经在google上搜索了,但是看不到像这样的呼叫:
my_example_task.state() == RUNNING
我的用例是我有一个外部(java)服务来进行代码转换。当我发送要进行代码转换的文档时,我想检查运行该服务的任务是否正在运行,如果没有运行,请(重新)启动它。
我相信我使用的是当前的稳定版本-2.4。
Answers:
返回task_id(由.delay()提供),然后向celery实例询问状态:
x = method.delay(1,2)
print x.task_id
询问时,使用以下task_id获取新的AsyncResult:
from celery.result import AsyncResult
res = AsyncResult("your-task-id")
res.ready()
async_result
。在您的用例中,您已经有实例,您可以使用。但是,如果您仅具有任务ID,并且需要实例化async_result
实例以进行调用,会发生什么情况async_result.get()
?这是AsyncResult
该类的实例,但是您不能使用原始类celery.result.AsyncResult
,需要从包装的函数中获取该类app.task()
。如果您愿意,可以这么做async_result = run_instance.AsyncResult('task-id')
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/…–
创建AsyncResult
从任务ID对象是在推荐的方式回答问题,获得任务的状态,当你拥有的唯一事情是任务ID。
但是,从Celery 3.x开始,有一些重要警告,如果不注意的话可能会咬人。这实际上取决于特定的用例场景。
为了让Celery记录任务正在运行,必须将设置task_track_started
为True
。这是一个测试此任务的简单任务:
@app.task(bind=True)
def test(self):
print self.AsyncResult(self.request.id).state
当task_track_started
is False
为默认值时,PENDING
即使任务已开始,状态显示仍为。如果设置task_track_started
为True
,则状态为STARTED
。
PENDING
表示“我不知道”。一个AsyncResult
与状态PENDING
并不意味着什么,更重要的是芹菜不知道任务的状态。这可能是由于多种原因造成的。
一方面,AsyncResult
可以使用无效的任务ID进行构造。这些“任务”将被Celery视为待处理:
>>> task.AsyncResult("invalid").status
'PENDING'
好的,因此没有人可以将明显无效的ID提供给AsyncResult
。足够公平,但它也有效果,AsyncResult
也将考虑已成功运行但Celery已忘记存在的任务PENDING
。同样,在某些用例场景中,这可能是个问题。问题的一部分取决于Celery如何配置为保留任务结果,因为它取决于结果后端中“逻辑删除”的可用性。(“ Tombstones”是Celery文档中使用的术语,用于记录任务如何完成的数据块。)使用is AsyncResult
根本不起作用。一个更令人烦恼的问题是,Celery默认使墓碑过期。的task_ignore_result
True
result_expires
设置默认设置为24小时。因此,如果您启动任务并将ID记录在长期存储中,并且在24小时后再创建一个ID AsyncResult
,则状态为PENDING
。
所有“实际任务”都从该PENDING
状态开始。因此,PENDING
继续执行某项任务可能意味着该任务已被请求,但再也没有进一步进展了(无论出于何种原因)。否则可能意味着任务已执行,但Celery忘记了状态。
AsyncResult
不会为我工作。我还可以做些什么?与跟踪任务本身相比,我更喜欢跟踪目标。我确实保留了一些任务信息,但这实际上是跟踪目标的第二要务。目标存储在独立于Celery的存储中。当请求需要执行计算取决于某个目标已经实现时,它会检查目标是否已经实现,如果是,则使用此缓存的目标,否则将启动将影响目标的任务,并发送至向HTTP请求发出响应的客户端,指示其应等待结果。
上面的变量名称和超链接适用于Celery4.x。在3.x中相应的变量和超链接是:CELERY_TRACK_STARTED
,CELERY_IGNORE_RESULT
,CELERY_TASK_RESULT_EXPIRES
。
每个Task
对象都有一个.request
属性,其中包含AsyncRequest
对象。因此,以下行给出了Task的状态task
:
task.AsyncResult(task.request.id).state
您还可以在任务执行期间创建自定义状态并更新其值。这个例子来自文档:
@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
老问题了,但是我最近遇到了这个问题。
如果您要获取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
apply_async
。返回的对象apply_async
是一个AsyncResult
对象,它确实具有Celery生成的任务的ID。
task_id
要求您自己生成任务ID。在您的评论中,您已经想到了一个超出 “我如何检查任务状态”和“如果您试图获取task_id ...”的原因,如果您有此需要,那是很好的,但事实并非如此(此外,uuid()
用于生成任务ID绝对不会超出Celery的默认设置。)
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}"
对于简单的任务,我们可以使用http://flower.readthedocs.io/en/latest/screenshots.html和http://policystat.github.io/jobtastic/进行监视。
对于复杂的任务,说一个处理许多其他模块的任务。我们建议在特定任务单元上手动记录进度和消息。
我在
就我而言,我正在检查Celery是否正在运行。
inspect_workers = task.app.control.inspect()
if inspect_workers.registered() is None:
state = 'FAILURE'
else:
state = str(task.state)
您可以通过检查来满足您的需求。
除了上述编程方法之外,可以轻松查看使用花任务的状态。
使用Celery Events进行实时监控。Flower是用于监视和管理芹菜群集的基于Web的工具。
官方文件: 花-芹菜监控工具
安装:
$ pip install flower
用法:
http://localhost:5555
res = method.delay()
print(f"id={res.id}, state={res.state}, status={res.status} ")
print(res.get())
x
怎么办?