使用mod_wsgi、Django、Celery和RabbitMQ部署生产环境时,每两次页面刷新触发一次DisabledBackend错误
解决Apache/mod_wsgi部署Django+Celery时间歇性
DisabledBackend错误的问题 最近我碰到了一个特别棘手的诡异问题:用Django、Celery和RabbitMQ搭建的服务,开发环境下所有功能跑起来都顺风顺水,但部署到生产环境用Apache2/mod_wsgi托管时,每两次刷新结果页面就会触发一次错误:'DisabledBackend' object has no attribute '_get_task_meta_for',错误刚好卡在执行task_state = <taskname>.AsyncResult(task_id).state这行代码的时候。
我的初始配置
先说明下,我的Celery配置是明确指定了backend的,看起来完全没问题:
app = Celery('<name>', broker='amqp://<user>:' + RABBITMQ_PASSWD + '@localhost:5672/<vhost>', backend='django-db', task_ignore_result=False, task_track_started=True, )
一步步排查的过程
- 一开始我试了所有常规操作:重启Celery、Apache服务,甚至重启整个服务器,清理Celery结果数据库,还换过不同的backend(比如Redis),但问题依然顽固存在。
- 我也看过Celery相关的解决方案页面,排除了Django自身配置的问题——毕竟开发环境完全正常,只有生产环境会间歇性"丢失"backend,呈现一次正常一次报错的交替现象。
- 翻遍了RabbitMQ日志、Apache访问/错误日志、Celery Worker日志,也没找到能直接定位问题的线索。
- 后来我做了个对比测试:直接用Django自带的
runserver运行生产环境代码,一切正常;只要切换到Apache/mod_wsgi部署,错误就会出现,这才把排查方向锁定到mod_wsgi的配置上。
问题根源与最终解决方案
最终确认问题出在WSGIDaemonProcess的配置上。我之前参考文档设置了这样的虚拟主机配置:
WSGIScriptAlias / <path>/wsgi.py WSGIDaemonProcess <name> python-home=<path to virtualenv> python-path=<path to django project> WSGIProcessGroup <name> WSGIApplicationGroup %{GLOBAL}
用这个配置时,就会出现每两次刷新交替报错的情况。
而当我移除上述守护进程配置,改用全局的mod_wsgi配置后,所有功能立刻恢复正常:
WSGIScriptAlias / <path>/wsgi.py WSGIPythonHome <path to virtualenv> WSGIPythonPath <path to django project>
推测原因是WSGIDaemonProcess的进程隔离机制,导致Celery的backend配置没有在所有子进程中正确初始化,才出现了间歇性无法获取任务元数据的情况。
内容的提问来源于stack exchange,提问作者Carsten
相关产品推荐
相关产品推荐

