背景:正確使用
我們有一個使用SQLAlchemy的ORM作爲一個Python Web應用程序。我們目前使用Gunicorn(同步工作人員)運行此應用程序。此應用程序僅用於響應長期請求(即提供大文件,請不要建議使用X-Sendfile/X-Accel-Redirect,因爲響應是從Python應用程序動態生成的)。
與Gunicorn同步工作者,當我們運行8個工人時,只有8個請求被同時服務。由於所有這些響應都是IO綁定的,我們希望切換到異步工作者類型以獲得更好的吞吐量。
我們已經在Gunicorn配置文件中將工作人員類型從sync更改爲eventlet。現在我們可以同時響應所有的請求,但是另一個神祕的(對我來說是神祕的)問題已經出現。
在應用程序中,我們在模塊級別有一個有作用域的會話對象。下面的代碼是從我們的orm.py文件:
uri = 'mysql://%s:%[email protected]%s/%s?charset=utf8&use_unicode=1' % (\
config.MYSQL_USER,
config.MYSQL_PASSWD,
config.MYSQL_HOST,
config.MYSQL_DB,
)
engine = create_engine(uri, echo=False)
session = scoped_session(sessionmaker(
autocommit=False,
autoflush=False,
bind=engine,
query_cls=CustomQuery,
expire_on_commit=False
))
我們的應用程序使用的會話是這樣的:當我們使用同步工人
from putio.models import session
f = session.query(File).first()
f.name = 'asdf'
session.add(f)
session.commit()
,從每次1個請求中使用會話。在我們切換到異步的eventlet worker之後,同一個worker中的所有請求共享相同的會話,這是不需要的。當一個請求提交會話或發生異常時,所有其他請求都會失敗,因爲會話是共享的。
在SQLAlchemy的文檔中,說scoped_session用於線程環境中的分離會話。異步worker中的AFAIK請求運行在同一個線程中。
問:
我們希望在異步工人每個請求單獨的會話。在SQLAlchemy中與異步工作者使用會話的正確方法是什麼?