2012-11-22 77 views
2

背景:正确使用

我们有一个使用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中与异步工作者使用会话的正确方法是什么?

回答