在其他地方看到了這樣一種處理方式
@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舞箍,一方面是線程安全置森,一方面是避免出現(xiàn)重復申請session導致連接池滿的問題汗茄。同時通過g訪問session看起來方便。
初期實現(xiàn)確實很爽畜吊,但是跑了一陣就遇到了很多問題步清。最常見的就是session異常沒有rollback導致請求失敗。這個錯誤隨機性很高榜晦,不好排查冠蒋。
我因為這個問題質(zhì)疑了好一陣Flask的實際能力,今天突然想通了乾胶,就是那個實現(xiàn)方式的鍋抖剿。
下面是我的推測,沒有經(jīng)過實際驗證
flask本身是單線程的识窿,通過wsgi服務器可以搞成多進程運行提高性能斩郎。那么相當于在一個線程里面,所有邏輯都共用了一個session腕扶。如果只是單純的接口孽拷,因為after_requests里面關閉了session吨掌,只要注意提交的時候捕獲一下異常即可半抱。
然而如果你的應用中在其他地方也在使用這個session,就很可能出問題了膜宋。
一些思路
如果你是純Flask應用窿侈,不涉及任何視圖函數(shù)之外的數(shù)據(jù)庫邏輯,請直接使用flask-sqlalchemy秋茫。它封裝的session默認是scoped_session史简。
如果還有很多外部代碼,一定保證你的session是可控的肛著。
簡單來說就是:
- 用就開圆兵,用完就關
- 盡量避免多個函數(shù)依賴之間同時使用session
- 使用scoped_session來保證線程安全