简体   繁体   English

将 SQLAlchemy 会话与 Celery 一起使用的正确方法是什么?

[英]What's the proper way to use SQLAlchemy Sessions with Celery?

I've been trying to figure out this for a while but a lot of answers I can find now are out-dated (posts from > 6 years ago), or less related.我一直试图弄清楚这一点,但我现在能找到的很多答案都是过时的(来自> 6年前的帖子),或者相关性较低。

The question is really how to deal with database sessions properly in celery.问题实际上是如何在 celery 中正确处理数据库会话。 My current setting is: I have a global DbEngine object that contains dsn , engine , and Session .我当前的设置是:我有一个包含dsnengineSession so every time if I want to use a session, I just call sess = db.Session() and start to use them inside my Flask app.所以每次如果我想使用 session,我只需调用sess = db.Session()并开始在我的 Flask 应用程序中使用它们。 It looks like the following:它如下所示:

#db.py
class DbEngine:
  def __init__(self, path, ...):
    self.dsn = self.create_dsn_from_file(path)
    self.engine = create_engine(self.dsn)
    self.Session = scoped_session(sessionmaker(bind=self.engine))

Until I introduced celery to my app, often I got various errors (Protocol error, sslSocket errors, etc).在我将 celery 引入我的应用程序之前,我经常遇到各种错误(协议错误、sslSocket 错误等)。 And I could not reproduce them locally, and it often gets fixed if I simply add retries to those tasks (it usually goes through with 3 retries).而且我无法在本地重现它们,如果我只是向这些任务添加重试,它通常会得到修复(它通常会重试 3 次)。 So I suspect that this might be caused by the Shared Sessions.所以我怀疑这可能是由共享会话引起的。

Then I decided to change my session for the celery app: every time if I need a session, I will actually create a new engine, create a new Session, and return the newly created Session() . Then I decided to change my session for the celery app: every time if I need a session, I will actually create a new engine, create a new Session, and return the newly created Session() . However, the similar but not exactly the same problem happened again (various protocol errors with different codes).但是,类似但不完全相同的问题再次发生(不同代码的各种协议错误)。

I saw that celery has its own SessionManager, but I couldn't find sample code of usage.我看到celery有自己的SessionManager,但是找不到使用示例代码。 I was thinking about the following structure:我正在考虑以下结构:

# celery_app.py

celery = ... 

session_manager = SessionManager()
engine, Session = session_manager.create_session(dsn)

and in the tasks I do:在我做的任务中:

# task_1.py
from celery_app import celery, Session

@celery.task
def tsk():
  sess = Session()
  sess.query(...)
  ... 
  sess.close()

But really not sure if it's the intended approach, since I am only calling the .create_session() once, and I don't know when and how I should call the other functions in the SessionManager.但真的不确定这是否是预期的方法,因为我只调用.create_session()一次,而且我不知道何时以及如何调用 SessionManager 中的其他函数。

For the background, I am using DB2.对于背景,我使用的是 DB2。

If anyone knows how to properly use SessionManager or has experience in using session with SQLAlchemy that'd be much appreciated if you can provide any insights.如果有人知道如何正确使用 SessionManager 或有使用 session 和 SQLAlchemy 的经验,如果您能提供任何见解,将不胜感激。 Thank you in advance!先感谢您!

Maybe not the answer you're looking for, but flask_sqlalchemy provides a Flask-friendly layer over SQLAlchemy that almost entirely removes the need to manage sessions manually.也许不是您正在寻找的答案,但flask_sqlalchemy在SQLAlchemy 上提供了一个对Flask 友好的层,几乎完全消除了手动管理会话的需要。 And it plays well with celery once you set up a ContextTask per the example in the Flask docs .一旦您按照Flask 文档中的示例设置了 ContextTask,它就可以很好地与 celery 配合使用。

Posting this hoping it helps someone out.发布这个希望它可以帮助某人。 In my case, we're using Fastapi, Postgres, Sqlalchemy and Celery.在我的例子中,我们使用的是 Fastapi、Postgres、Sqlalchemy 和 Celery。

I had the same issue and it was very challenging.我遇到了同样的问题,而且非常具有挑战性。 Lots of cryptic errors from our postgres db looking like the connections were being stopped mid stream.来自我们的 postgres 数据库的许多神秘错误看起来像是在 stream 中间停止了连接。 PG_TUPLES_OK and no message from the libpq , AttributeError("'_NoResultMetaData' object has no attribute '_indexes_for_keys'") ... etc etc PG_TUPLES_OK and no message from the libpqAttributeError("'_NoResultMetaData' object has no attribute '_indexes_for_keys'") ... 等等

TL;DR TL;博士

Sqlalchemy pools connections by default in a non-threadsafe manner, Celery forks processes by default: one or the other needs to be changed. Sqlalchemy 默认以非线程安全的方式池连接,Celery 默认分叉进程:需要更改其中一个或另一个。

Solution 1) Turn off Sqlalchemy pooling *we ended up going with this to maintain better concurrency解决方案 1) 关闭 Sqlalchemy 池*我们最终这样做是为了保持更好的并发性

Sql Alchemy Docs Sql 炼金术文档

from sqlalchemy.pool import NullPool
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, poolclass=NullPool
)

Solution 2) Make Celery run as a single process with no forking解决方案 2) 使 Celery 作为单个进程运行,无需分叉

celery -A celery_worker.celery worker -E --loglevel=info --pool=solo

Article on Celery pooling This solution worked, but meant that all of our celery tasks would be running serially, which eliminated the errors but we needed more bandwidth. 关于 Celery 池化的文章该解决方案有效,但意味着我们所有的 celery 任务都将连续运行,这消除了错误,但我们需要更多带宽。 This may be fine for certain applications.这可能适用于某些应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SQLAlchemy事务与会话的正确顺序是什么? - What is the proper order of SQLAlchemy transactions vs sessions? SQLalchemy以声明方式描述关联对象的正确方法是什么 - What's the proper way to describe an associative object by SQLalchemy the declarative way PySQLPool和Celery,正确的使用方式吗? - PySQLPool and Celery, proper way to use it? 在 SQLAlchemy (Python) 中联合查询列表的正确方法是什么? - What's the proper way to UNION a list of queries in SQLAlchemy (Python)? 在 Flask SQLALchemy 模型中处理业务逻辑的正确方法是什么? - What's the proper way of handling business logic in Flask SQLALchemy models? 使用** kwargs的正确方法是什么? - What's the proper way to use **kwargs? 什么是使用django芹菜和redis异步刮取并存储我的结果的正确方法并存储我的? - What's the proper way to scrape asynchronously and store my results using django celery and redis and store my? 使用SQLAlchemy为这种继承建模的正确方法是什么? - What is the proper way to model this type of inheritance with SQLAlchemy? 芹菜+ sqlalchemy以什么方式严重处理多个工人? - In what way does celery + sqlalchemy badly handle multiple workers? 在关系中使用映射属性的正确方法是什么,仍然允许在sqlalchemy中进行预先加载? - What is the proper way to use a mapped attribute in a relationship and still allow for eager loading in sqlalchemy?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM