我已经在 Heroku 上的 Django 站点上成功使用了 Celery,但它刚刚开始生成下面的错误,这导致它停止运行。看起来 postgres 遇到了问题,但我对如何修复它感到困惑,因为是 Celery 而不是我的代码有问题(我认为......)。
我使用 CloudAMPQ 作为代理,我的 Django 设置包括:
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
这是 Heroku 日志的回溯:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.5/site-packages/kombu/utils/__init__.py", line 323, in __get__
return obj.__dict__[self.__name__]
KeyError: 'scheduler'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.OperationalError: SSL SYSCALL error: Bad file descriptor
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.5/site-packages/billiard/process.py", line 292, in _bootstrap
self.run()
File "/app/.heroku/python/lib/python3.5/site-packages/celery/beat.py", line 553, in run
self.service.start(embedded_process=True)
File "/app/.heroku/python/lib/python3.5/site-packages/celery/beat.py", line 470, in start
humanize_seconds(self.scheduler.max_interval))
File "/app/.heroku/python/lib/python3.5/site-packages/kombu/utils/__init__.py", line 325, in __get__
value = obj.__dict__[self.__name__] = self.__get(obj)
File "/app/.heroku/python/lib/python3.5/site-packages/celery/beat.py", line 512, in scheduler
return self.get_scheduler()
File "/app/.heroku/python/lib/python3.5/site-packages/celery/beat.py", line 507, in get_scheduler
lazy=lazy)
File "/app/.heroku/python/lib/python3.5/site-packages/celery/utils/imports.py", line 53, in instantiate
return symbol_by_name(name)(*args, **kwargs)
File "/app/.heroku/python/lib/python3.5/site-packages/djcelery/schedulers.py", line 151, in __init__
Scheduler.__init__(self, *args, **kwargs)
File "/app/.heroku/python/lib/python3.5/site-packages/celery/beat.py", line 185, in __init__
self.setup_schedule()
File "/app/.heroku/python/lib/python3.5/site-packages/djcelery/schedulers.py", line 158, in setup_schedule
self.install_default_entries(self.schedule)
File "/app/.heroku/python/lib/python3.5/site-packages/djcelery/schedulers.py", line 251, in schedule
self._schedule = self.all_as_schedule()
File "/app/.heroku/python/lib/python3.5/site-packages/djcelery/schedulers.py", line 164, in all_as_schedule
for model in self.Model.objects.enabled():
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/models/query.py", line 258, in __iter__
self._fetch_all()
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/models/query.py", line 1074, in _fetch_all
self._result_cache = list(self.iterator())
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/models/query.py", line 52, in __iter__
results = compiler.execute_sql()
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 848, in execute_sql
cursor.execute(sql, params)
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/app/.heroku/python/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/app/.heroku/python/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.OperationalError: SSL SYSCALL error: Bad file descriptor
我现在已经解决了这个问题...我的 Django 代码中有一行在过去导致了内部服务器错误 - 我认为,在 Django 启动的早期,它试图在创建模型的迁移已经运行。
我已经解决了这个问题,但注意到这些“SSL SYSCALL 错误”大约在同一时间开始。所以我删除了那行代码,Celery 又启动了。
这可能是巧合。我不明白为什么这会解决问题。
理想情况下,我仍然想了解上面的错误实际上意味着什么,这样我将来就有更好的机会解决这样的问题。
我有同样的错误,我解决了。 就我而言,问题是我的 django 应用程序之一中的自定义 AppConfig。
我的文件夹
my_django_app/
__init__.py
apps.py
...
我有一个文件
my_django_app/__init__.py
像这样
default_app_config="my_django_app.apps.MyAppConfig"
和文件
my_django_app/apps.py
像这样
class ChallengeConfig(AppConfig):
name = 'appConfig'
verbose_name = "djangoAppConfig"
def ready(self):
... # custom logic
去掉线后
default_app_config="my_django_app.apps.MyAppConfig"
芹菜又可以工作了
如果您有类似的情况,请删除自定义 AppConfig 并使用 celery 定期任务而不是自定义 AppConfig。 django_celery_beat 对 AppConfig 做了一些奇怪的事情,所以如果你有一个自定义的 AppConfig 它会产生问题
我的Python要求:
Django==1.11.29
celery==4.4.7
django_celery_beat==1.6.0
我知道这是几年前提出的问题,但这是唯一与我的问题相关的问题。
在我的例子中,CONN_MAX_AGE 设置为 600。减少到 0,以便有无限的持久连接。
来自文档:
持久连接避免了在每个请求中重新建立与数据库的连接的开销。它们由 CONN_MAX_AGE 参数控制,该参数定义连接的最大生命周期。每个数据库都可以独立设置。
默认值为0,保留每次请求结束时关闭数据库连接的历史行为。要启用持久连接,请将 CONN_MAX_AGE 设置为正整数(秒)。对于无限制的持久连接,请将其设置为 None。
Django 在第一次进行数据库查询时打开与数据库的连接。它保持此连接打开并在后续请求中重用它。一旦连接超过 CONN_MAX_AGE 定义的最大期限或不再可用,Django 就会关闭连接。
详细来说,每当 Django 需要但还没有数据库连接时,它就会自动打开一个到数据库的连接 - 要么因为这是第一个连接,要么因为上一个连接已关闭。
在每个请求开始时,如果连接已达到最大寿命,Django 将关闭连接。如果您的数据库在一段时间后终止空闲连接,您应该将 CONN_MAX_AGE 设置为较低的值,以便 Django 不会尝试使用已被数据库服务器终止的连接。 (这个问题可能只影响流量非常低的网站。)
在每个请求结束时,如果连接已达到最长期限或处于不可恢复的错误状态,Django 将关闭连接。如果在处理请求时发生任何数据库错误,Django 会检查连接是否仍然有效,如果不有效则将其关闭。因此,数据库错误最多影响一个请求;如果连接变得不可用,下一个请求将获得新的连接。
我们有一个非常相似的错误消息,并且几乎有相同的堆栈(Heroku、Django、Celery、Postgres)。我们的问题是由于模块加载时的数据库调用造成的。我们的其中一种表格如下所示:
class BatteryForm(forms.Form):
battery = forms.ModelMultipleChoiceField(
label='Battery type',
required=True,
queryset=Battery.objects.all(),
initial=[Battery.objects.get(name='battery-name')],
widget=forms.CheckboxSelectMultiple,
)
initial 中的值在模块加载时进行了数据库调用,以
SSL SYSCALL error
结尾,但仅限于 Celery 工作人员。
我不知道为什么会发生这种情况,或者只在生产中引起问题,但看看其他答案,很可能是在启动应用程序时与数据库通信。