Heroku上的烧瓶和芹菜:sqlalchemy.exc.DatabaseError:(psycopg2.DatabaseError)SSL错误:解密失败或错误的记录mac

Anc*_*nia 0 python heroku celery flask flask-sqlalchemy

我正在尝试在heroku上部署Flask应用程序,该应用程序在Celery中使用后台任务。我已经实现了应用程序工厂模式,以便将celery进程不绑定到flask应用程序的任何一个实例。

这在本地有效,但我还没有看到错误。但是,当部署到heroku时,总是会出现相同的结果:celery任务(我只使用一个)在第一次运行时成功,但是对该任务的所有后续celery调用均失败sqlalchemy.exc.DatabaseError: (psycopg2.DatabaseError) SSL error: decryption failed or bad record mac。如果我重新启动芹菜工人,循环将继续。

多个 问题表明此错误,但没有一个问题指定正确的解决方案。最初,我认为实现应用程序工厂模式将阻止此错误的出现,但还不完全如此。

app/__init__.py我创建celery和db对象中:

celery = Celery(__name__, broker=Config.CELERY_BROKER_URL)
db = SQLAlchemy()

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])

    db.init_app(app)
    return app
Run Code Online (Sandbox Code Playgroud)

我的flask_celery.py文件创建了实际的Flask应用程序对象:

import os
from app import celery, create_app

app = create_app(os.getenv('FLASK_CONFIG', 'default'))
app.app_context().push()
Run Code Online (Sandbox Code Playgroud)

我用以下命令开始芹菜: celery worker -A app.flask_celery.celery --loglevel=info

实际的芹菜任务如下所示:

@celery.task()
def task_process_stuff(stuff_id):
    stuff = Stuff.query.get(stuff_id)
    stuff.processed = True
    db.session.add(stuff)
    db.session.commit()
    return stuff
Run Code Online (Sandbox Code Playgroud)

通过以下方式调用:

task_process_stuff.apply_async(args=[stuff.id], countdown=10)
Run Code Online (Sandbox Code Playgroud)

图书馆版本

  • 烧瓶0.12.2
  • SQLAlchemy 1.1.11
  • Flask-SQLAlchemy 2.2
  • 芹菜4.0.2

Anc*_*nia 6

解决方案是db.engine.dispose()在任务开始时添加,在开始任何工作之前处理所有数据库连接:

@celery.task()
def task_process_stuff(stuff_id):
    db.engine.dispose()
    stuff = Stuff.query.get(stuff_id)
    stuff.processed = True
    db.session.commit()
    return stuff
Run Code Online (Sandbox Code Playgroud)

由于我在所有任务中都需要此功能,因此将其添加到task_prerun

@task_prerun.connect
def on_task_init(*args, **kwargs):
    db.engine.dispose()
Run Code Online (Sandbox Code Playgroud)

  • 谁能解释这个问题的根本原因?为什么这会影响 Celery 工人而不是 Gunicorn 工人? (2认同)