我在Heroku上有一个Django应用程序,它使用Celery的 delay 方法调用任务,该方法应该将额外的处理传递给worker。但是当我向相应的视图发出http请求时,Heroku web dyno会挂起并最终导致请求超时。这是一个测试任务(应用程序称为等待时间):
@task
def test_tasks(message, name='waittimes.tasks.test_tasks'):
print message
测试视图:
class TaskTest(View):
def get(self, request):
print "about to call the task"
test_tasks.delay("the task was successful!")
return HttpResponse("view was successful")
如果我向此视图发出http请求,我希望“任务成功”输出到控制台并回复“视图成功”。当我向计算机上的开发服务器发出请求时,这种情况会成功发生。如果我在我的应用程序的Heroku环境中启动django shell并使用django的测试客户端发出请求,它也可以工作。
app[celeryd.1]: [2013-06-26 23:57:48,018: INFO/MainProcess] Got task from broker: waittimes.tasks.test_tasks[67036069-b49e-45ba-aef4-3c64d7161a67]
app[celeryd.1]: [2013-06-26 23:57:48,133: WARNING/PoolWorker-3] the task was successful!
app[celeryd.1]: [2013-06-26 23:57:48,200: INFO/MainProcess] Task waittimes.tasks.test_tasks[67036069-b49e-45ba-aef4-3c64d7161a67] succeeded in 0.09690284729s: None
但是当我直接向Heroku url发出请求时,请求会挂起,我最终会从Heroku获得一个可怕的H12超时错误。
heroku[router]: at=error code=H12 desc="Request timeout" method=GET path=/task/test/ dyno=web.1 connect=2ms service=30000ms status=503 bytes=0
我知道调用该任务会导致问题,因为“即将调用任务”确实会在控制台中打印出来。所以问题是系统无法解析“延迟”(和apply_async)方法。它只是挂起并且不返回异步对象。这只有在代码在web dyno进程上运行时才会发生。
到目前为止,这些是我的结论:
1)任务已正确注册,我的Redis代理正在工作,因为当我使用shell中的测试客户端调用视图时一切正常(但是这是在Heroku上的单独shell进程上运行,而不是web dyno通常收到请求)
2)系统正确地路由和调度请求的处理程序,因为“即将调用任务”被打印。它似乎不是Heroku路由器的问题。
3)问题与特定视图无关,因为即使像这样的剥离测试用例也不起作用
除了直接的解决方案之外,任何有关如何进一步调试的建议也值得赞赏。
答案 0 :(得分:1)
好吧,这可能不是直接的答案,但是鉴于这个问题的年代以及它无人值守的时间,我将继续为所有不幸遇到此问题的人提供我的见解。< / p>
这个特殊问题似乎文献记载不多,很难找到,我只是在百灵鸟上在Heroku上建立侧项目时遇到了这个问题。
Heroku似乎有一种地方性之处,即某些Python函数调用在平台上的行为与在本地(或在任何常规Python部署上)不同。
就我而言,这里的问题是我的Celery任务正在调用Python的time.sleep()
函数。
作为一个测试案例,我使用time.sleep(1)
只是为了在日志中证明任务确实是异步执行的。我已经在普通基础架构(包括虚拟机)上成功运行了此测试多次。
当我将此测试移植到Heroku时,我遇到了gentro完全相同的问题。日志清楚地表明Celery和我的经纪人已正常初始化,并且知道我的应用程序,但是,当我通过Django视图进行呼叫时,我的Web dyno神秘地将H12超时作为唯一的日志消息。 / p>
当我注释掉sleep
呼叫后,一切都完全正常了。
TL; DR-检查导致您执行芹菜任务的调用堆栈,确保您没有留下任何可能导致Heroku dyno抢占的功能,例如sleep()
我并不是说这是造成原始问问者问题的专门原因,但是,如果您看到此行为,那绝对是潜在原因之一。