天天看點

web.py——session

使用web.py過程中,遇到兩個疑問:

1、web.py如何管理相對自動的管理session?

2、session緩存的更新為何會有延遲?

通過學習web.py架構中session相關源碼,有了答案:

1、web.py通過Session執行個體作為公共的session使用接口,Session執行個體基于threading子產品提供線程安全的空間用于加載session,加載session依賴sessionID,sessionID-session字典序列化後存儲于磁盤等位置。相同終端發起不同請求,通過不同線程到達應用程式,攜帶相同sessionID,加載相同session,是以擁有相同上下文環境。

2、session被加載至Session執行個體後可以被修改,使用者請求處理完畢後更新至session緩存,是以更新存在延遲。另外,session更新基于覆寫機制,而不是合并機制。

以下為具體學習記錄:

一、session生命周期 1、應用啟動時,聲明Application執行個體,聲明Session執行個體(同時将session處理器添加至Application處理器隊列),添加Session執行個體存儲處理器。 2、請求到達時,依次調用前置應用處理器、請求處理方法、後置應用處理器。為確定Session執行個體全局可見,Session執行個體存儲處理器必須為前置應用處理器,且存儲位置必須全局可見。session處理器需完成事前加載、事後更新等工作,通過try...finally...語句同時實作前置應用處理器和後置應用處理器。 3、Session執行個體存儲處理器也是前置應用處理器之一,為了Session執行個體全局可見,需要将Session執行個體存儲處理器添加至一級應用的處理器隊列中,并選擇全局可見的位置存儲Session執行個體,如web.ctx.session 4、session處理器的前置部分,包含清理過期session、加載session和session逾時處理,出現session逾時且不忽略時,将觸發SessionExpired異常并将記錄sessionID的cookie設定為逾時 5、session處理器的後置部分,更新session緩存。因session更新存在延遲,延遲期間加載相同session并不能獲得最新session。更新session緩存采取覆寫機制。

二、DiskStore類 DiskStore類用于根據sessionID對session進行增删改查 1、__init__(self, root) 初始化方法。root參數為session緩存根目錄,確定根目錄存在。 2、_get_path(key) session檔案路徑生成方法。根據key和self.root生成session檔案路徑 3、__contain__(self, key) in操作符的魔法方法。判斷key對應的session是否已經存在,不考慮是否過期 4、__getitem__(self, key)/__setitem__(self, key, value)/__delitem__(key) 模拟字典操作的魔法方法。查詢、更新、删除session,不考慮是否過期 5、cleanup(self, timeout) 删除過期session。周遊根目錄下全部session,删除過期session 6、encode(self, session_dict)/decode(self, session_data) session資料序列化和反序列化方法,以便可以通過檔案存儲session,繼承自父類Store。

三、Session類 提供線程安全的空間加載session;提供Web架構中管理session需要的方法 1、__init__(self, app, store, initializer=None) 初始化方法。設定session相關配置,向app添加加載session的處理器。 Session設定了__slots__屬性、提供線程安全變量空間的_data屬性、重寫了字典操作符相關魔法方法,将session在Session執行個體中的管理和存儲分離開。 為了實作加載一次session整個Web架構可用的目的,加載session的處理器應該添加至一級應用的處理器清單中,得到的Session執行個體也應該儲存至整個Web架構均可以通路的位置,如web.ctx.session 2、__contain__(self, key) in操作符的魔法方法。判斷key是否存在于session中 3、__getattr__(self, key)/__setattr__(self, key, value)/__delattr__(self, key) 點操作符的魔法方法。使Session執行個體支援通過點操作符通路session中的具體内容,__setattr__(self, key, value)方法也支援對Session執行個體的屬性進行操作,Session執行個體和session出現同名鍵值對時,優先處理Session執行個體 4、_processor(self, handler) 應用處理器。用于在使用者請求被具體處理前加載session,使用者請求處理完畢後更新session。通過try...finally...關鍵字組,在一個應用處理器内實作了使用者請求處理前後兩次處理。 5、_cleanup(self) 過期session清理方法,應用處理器的一部分。調用self.store執行個體的cleanup(timeout)方法,清理過期session。 6、_load(self) session加載方法,應用處理器的一部分。若使用者請求攜帶了sessionID、sessionID格式合法、sessionID未過期,将讀取sessionID代表的session,并更新self._data session不存在或格式不合法或已過期,将重新生成sessionID,并根據self._initializer更新self._data,self._initializer應該為dict類型或自動更新self._data的可調用對象 session過期且Session執行個體設定為不忽略過期行為,将觸發SessionExpired異常并在使用者請求響應中設定記錄sessionID的cookie項為過期狀态 session存在且請求IP變化且Session執行個體設定為不忽略IP變化行為,将觸發SessionExpired異常并在使用者請求響應中設定記錄sessionID的cookie項為過期狀态 7、_check_expiry(self) 檢測session是否過期,在self._load()方法中被調用,self._load()方法在self._cleanup()後調用。基于key in self.store判斷。 session過期且Session執行個體設定為不忽略過期行為,将調用self.expired()方法進行session過期處理。 8、_validate_ip(self) 檢測請求IP是否變化,在self._load()方法中被調用,确定session存在後被調用。 session存在且請求IP變化且Session執行個體設定為不忽略IP變化行為,将調用self.expired()方法進行session過期處理。 9、expired(self) session過期處理方法。設定self._killed屬性為True,表示session已過期;直接調用self._save()方法進行session更新相關操作;觸發SessionExpired異常。 10、_save(self) session和sessionID更新方法。通過self.store[sessionID] = self._data更新session緩存,通過設定響應頭更新記錄sessionID的cookie 11、_setcookie(self, session_id, expires='', **kw) 記錄sessionID的cookie更新方法。 12、_generate_session_id(self) sessionID生成方法。生成的sessionID要判斷是否正在被使用。 13、kill(self) session删除方法。del self.store[sessionID],且設定self._killed為True,以便self._save()方法進行相應處理