即使在任务启动后,AsyncResult(task_id) 也会返回“PENDING”状态

Posted

技术标签:

【中文标题】即使在任务启动后,AsyncResult(task_id) 也会返回“PENDING”状态【英文标题】:AsyncResult(task_id) returns "PENDING" state even after the task started 【发布时间】:2014-08-22 11:21:23 【问题描述】:

在项目中,我尝试轮询一个长时间运行的任务的 task.state 并更新其运行状态。它在开发中工作,但是当我将项目移动到生产服务器上时它不会工作。即使我可以看到任务从花开始,我也一直在“等待”。但是,当 task.state == 'SUCCESS' 时,我仍然可以在任务完成时更新结果。我在生产中使用 python 2.6、Django 1.6 和 Celery 3.1,结果后端 AMQP。

@csrf_exempt
def poll_state(request):
    data = 'Fail'

    if request.is_ajax():
            if 'task_id' in request.POST.keys() and request.POST['task_id']:
                    task_id = request.POST['task_id']
                    email = request.POST['email']
                    task = AsyncResult(task_id)
                    print "task.state=", task.state
                    if task.state == 'STARTED':
                            task_state = 'Running'
                            data = 'Running'
                            #data = 'Running'
                    elif task.state == 'PENDING' or task.state == 'RETRY':
                            task_state = 'Waiting'
                            data = 'Pending'
                    elif task.state == 'SUCCESS':
                            task_state = 'Finished'
                            if task.result:
                                    data = task.result
                            else:
                                    data = 'None'

                    else:
                            task_state = task.state
                            data = 'Error'
                            print 'data status =', task_state
            else:
                    task_state = task.state
                    data = 'Error'
    else:
            task_state = task.state
            data = "Error"

    json_data = json.dumps('task_state':task_state, 'task_data':data)

 return HttpResponse(json_data, mimetype='application/json')

另一方面,flower 总是离线显示工人的状态,但任务状态是正确的。使用 celery events 3.1.12 (Cipter) 时,它显示正确的工人状态。

【问题讨论】:

【参考方案1】:

对于 Celery 4.1.0 和 Django 1.11.7,这是您在 config.py 文件中需要的:

正确:

task_track_started = True

也正确:

CELERY_TASK_TRACK_STARTED = True

错了!:

CELERY_TRACK_STARTED = True

我花了 2 个小时才弄明白。希望这在不久的将来能为某人服务

【讨论】:

如果您认为上述解决方案不适合您,请使用 CELERY_TRACK_STARTED = True【参考方案2】:

可能与CELERY_TRACK_STARTED 设置有关。引用文档:

CELERY_TRACK_STARTED

如果为 True,任务将报告其状态为 当任务由工作人员执行时“开始”。默认值为 错误,因为正常行为是不报告该级别 粒度。任务处于待处理、已完成或正在等待 重试。有一个“开始”状态对于当有 长时间运行的任务,需要报告哪个任务是 正在运行。

也许您在开发设置中有CELERY_TRACK_STARTED = True,但在生产环境中没有?

【讨论】:

我的 settings.py 中有 'CELERY_TRACK_STARTED = True',我用 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 设置了 celeryconfig.py。问题是 AsyncResult(task_id).state 总是返回“PENDING”状态,因此当任务开始时我的模板无法更新为“STARTED”。但是花卉和芹菜事件监视器都显示任务正确启动。很困惑。 你能在你的生产运行的终端上运行celery inspect conf --app your_app_name来检查设置CELERY_TRACK_STARTED是否加载良好? 这就是问题所在! app.conf 直到我在 tasks.py 中明确设置后才会更新。我猜 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 没有工作。我仍然对为什么会发生这种情况感到困惑。【参考方案3】:

对于使用django-celery-email 的人——必须有以下设置:

CELERY_EMAIL_TASK_CONFIG = 
    'name': 'djcelery_email_send',
    'ignore_result': False,


CELERY_TASK_TRACK_STARTED = True
CELERY_EMAIL_CHUNK_SIZE = 1 

我相信我遇到的类似问题是由于将'ignore_result' 设置为True。来自django-celery-email 文档:

results 将是芹菜 AsyncResult 对象的列表,您可以 忽略,或用于检查邮件投递任务的状态,甚至 如果需要,请等待它完成。您必须启用结果后端 如果需要,在 CELERY_EMAIL_TASK_CONFIG 中将 ignore_result 设置为 False 使用这些。您还应该在中设置 CELERY_EMAIL_CHUNK_SIZE = 1 如果您担心任务状态和结果,请进行设置。

希望这对其他人有所帮助,同样也花了几个小时来解决这个问题......

【讨论】:

以上是关于即使在任务启动后,AsyncResult(task_id) 也会返回“PENDING”状态的主要内容,如果未能解决你的问题,请参考以下文章

定时任务Task

Activity的任务栈Task以及启动模式与Intent的Flag详解

即使重新启动后,我如何每天回忆方法?

Android Gradle-应用安装后如何运行任务

uc/os-ii启动后,即调用Osstart()后,系统的数据结构怎样

芹菜 - 无法获取任务结果