概述
由於PHP的工作機制,它並沒有一個daemon線程,來定時地掃描session資訊並判斷其是否失效。當一個有效請求發生時,PHP會根據全域變數 session.gc_probability/session.gc_divisor(同樣可以通過php.ini或者ini_set()函數來修改) 的值,來決定是否啟動一個GC(Garbage Collector)。預設情況下,session.gc_probability = 1,session.gc_divisor =100,也就是說有1%的可能性會啟動GC。GC的工作,就是掃描所有的session資訊, 用目前時間減去session的最後修改時間(modified date),同session.gc_maxlifetime參數進行比較,如果存留時間已經超過gc_maxlifetime,就把該session刪 除。
gc_maxlifetime無效
那為什麼會發生gc_maxlifetime無效的情況呢?
在預設情況下,session資訊會以文字檔的形式,被儲存在系統 的臨時檔案目錄中。在Linux下,這一路徑通常為\tmp,在Windows下通常為C:\Windows\Temp。當伺服器上有多個PHP應用時, 它們會把自己的session檔案都儲存在同一個目錄中。同樣地,這些PHP應用也會按一定機率啟動GC,掃描所有的session檔案。問 題在於,GC在工作時,並不會區分不同網站的session。舉例言之,網站A的gc_maxlifetime設定為2小時,網站B的 gc_maxlifetime設定為預設的24分鐘。當網站B的GC啟動時,它會掃描公用的臨時檔案目錄,把所有超過24分鐘的session檔案全部刪 除掉,而不管它們來自於網站A或B。這樣,網站A的gc_maxlifetime設定就形同虛設了。找到問題所在,解決起來就很簡單了。修改session.save_path參數,或者使用session_save_path()函數,把儲存session的目錄指向一個專用的目錄,gc_maxlifetime參數工作正常了。
還有一個問題就是,gc_maxlifetime只能保證session生存的最短時間,並不能夠儲存在超過這一時間之後session資訊立即會得到 刪除。因為GC是按機率啟動的,可能在某一個長時間內都沒有被啟動,那麼大量的session在超過gc_maxlifetime以後仍然會有效。解決這 個問題的一個方法是,把session.gc_probability/session.gc_divisor的機率提高,如果提到100%,就會徹底解 決這個問題,但顯然會對效能造成嚴重的影響。另一個方法是自己在代碼中判斷當前session的存留時間,如果超出了gc_maxlifetime,就清 空當前session。
gc工作原理
php session GC功能,就是Garbage Collector。這個GC啟動的時候,會清除那些已經“逾時”的session。它的工作原理是這樣的:
- 使用者訪問並登陸網站,這時候後台會調用session_start來嘗試產生一個會話(如果已經有會話,則相當於一次有效會話請求)
- 對於這樣的每一次有效會話請求(Request),apache的php模組會根據session相關的全域變數gc_probability/gc_divisor =>計算出啟動GC的機率,並由此機率來決定在這次請求中是否應該啟動GC。舉例來說,session.gc_probability的預設值為1,session.gc_divisor的預設值為100,則啟動“記憶體回收”器的機率是1%,這就意味著在每100次請求中,會有可能清理一次到期會話
- 如果GC啟動,則GC會掃描當前會話所在路徑(session.save_path)下的所有會話檔案,並根據另外一個全域變數session.gc_maxlifetime的多少來判斷哪些session已經到期(“目前時間”與“會話檔案的atime或者mtime”之間的差大於gc_maxlifetime:到期),並刪除這些到期的session
- 如果你在一個session啟動後,長時間沒有任何互動操作(譬如,不停地碼字,沒有提交或者儲存為草稿),那麼你的儲存在背景會話檔案將得不到機會被修改或者訪問,在gc_maxlifetime(預設值1440秒=24分鐘)時間後,它有可能因失效而被清理,這以後你再提交,就會因為會話失效而報錯
理解
- session_id儲存在瀏覽器(用戶端)的cookie中,關閉瀏覽器儲存sessiond_id的cookie失效,這時候無法訪問原來session檔案。伺服器端session檔案可能存在,還未刪除。
- 當一個使用者,24分鐘沒有任何操作(向伺服器發送請求,瀏覽器開啟著),session檔案可能被gc記憶體回收了,24分鐘後訪問,將建立跟原session_id相同的session新檔案,此時原有的session檔案內容將不存在了。
- 自動登入,不是設定session_id的cookie的有效時間,是在瀏覽器端儲存包含登入資訊(如使用者名稱,密碼)的cookie。
- 一個session_id的作用時間 到 瀏覽器關閉結束,再次開啟瀏覽器,是產生了新的session_id(新的session檔案)。
- 在伺服器端判斷session檔案是否無效(刪除),目前時間-檔案修改時間 > gc_maxlifetime,此時失效。
- 每次指令碼執行,都修改檔案修改時間
原文
http://blog.csdn.net/21aspnet/article/details/7218923