【Flask/SQLAlchemy】关于session处理的一点经验

在其他地方看到了这样一种处理方式

@self.app.before_request
def init_session():
    g.session = self.session_factory()

@self.app.after_request
def close_session(response):
    g.session.close()
    return response

这里的session_factory()

self.session_factory = scoped_session(sessionmaker(self.engine))

这样做的目的是在同一个线程能保证有唯一session,一方面是线程安全,一方面是避免出现重复申请session导致连接池满的问题。同时通过g访问session看起来方便。

初期实现确实很爽,但是跑了一阵就遇到了很多问题。最常见的就是session异常没有rollback导致请求失败。这个错误随机性很高,不好排查。

我因为这个问题质疑了好一阵Flask的实际能力,今天突然想通了,就是那个实现方式的锅。

下面是我的推测,没有经过实际验证

flask本身是单线程的,通过wsgi服务器可以搞成多进程运行提高性能。那么相当于在一个线程里面,所有逻辑都共用了一个session。如果只是单纯的接口,因为after_requests里面关闭了session,只要注意提交的时候捕获一下异常即可。

然而如果你的应用中在其他地方也在使用这个session,就很可能出问题了。

一些思路

如果你是纯Flask应用,不涉及任何视图函数之外的数据库逻辑,请直接使用flask-sqlalchemy。它封装的session默认是scoped_session。

如果还有很多外部代码,一定保证你的session是可控的
简单来说就是:

  • 用就开,用完就关
  • 尽量避免多个函数依赖之间同时使用session
  • 使用scoped_session来保证线程安全

你可能感兴趣的:(【Flask/SQLAlchemy】关于session处理的一点经验)