Session活化:從硬盤上讀取序列化的session到內存中
Session鈍化:把內存中的session序列化到硬盤上
Tomcat中兩種Session鈍化管理器
session鈍化機制是由sessionManager管理
tomcat提供了以下這兩種session處理方式
1 2 | org.apache.catalina.session.StandarManager org.apache.catalina.session.Persistentmanager |
StandarManager是tomcat的session默認處理方式,如果配置Persistentmanager則使用Persistentmanager,沒有配置則使用StandarManager。
1. StandarManager
當Tomcat服務器關閉或者重啓時tomcat服務器會將當前內存中的session對象鈍化到服務器文件系統中;
另一種情況是web應用程序被重新加載時(其實原理也是重啓tomcat),內存中的session對象也會被鈍化到服務器的文件系統中
當系統啓動時,會把序列化到硬盤上session重新加載到內存中來。這樣用戶還保持這登錄狀態,提供系統的可用性。
只有在tomcat關閉和啓動的時候纔會活化和鈍化session 強制kill掉tomcat是不會把session鈍化到硬盤上的。
2. Persistentmanager
可以將內存中長時間不用的session鈍化到硬盤上,減少內存的佔用。
比如:當網站有大量用戶訪問的時候,服務器會創建大量的session,會佔用大量的服務器內存資源,當用戶開着瀏覽器一分鐘不操作頁面的話建議將session鈍化,將session生成文件放在tomcat工作目錄下。
那怎麼該設置呢?
在 /WebRoot/META-INF 目錄下創建 context.xml文件(也可以在tomca目錄下的其他四個地方創建,在這裏建是爲了只對這個網站起作用),配置如下:
1 2 3 4 5 6 | <!--?xml version= "1.0" ?--> <context> <manager classname= "org.apache.catalina.session.PersistentManager" maxidleswap= "1" > <store classname= "org.apache.catalina.session.FileStore" directory= "sessionDir" > </store></manager> </context> |
Session活化 doLoad() 方法
在當前程序重新啓動的時候,調用doLoad() 方法進行活化session
1. 清空sessions中的session(剛啓動,sessions中應該是沒有session的)
1 | protected Map<string, session= "" > sessions = new ConcurrentHashMap<>();</string,> |
1. 獲取當前項目的WebappClassLoader
2. 從硬盤中讀取session,並把session反序列化成StandardSession對象。然後激活當前的session,並判斷當前session是否過期
activate() 方法
這個方法迭代執行了所有在web.xml中註冊的session活化的listener監聽器。
expire() 方法
expire方法是判斷session是否過期,如果過期則執行所有在web.xml中註冊過所有的HttpSessionListener的sessionDestroyed()方法
Session鈍化 unLoad() 方法
在當前程序關閉的時候,調用unLoad() 方法進行鈍化session
1. 獲取輸出文件流
2. 遍歷內存中所有的session,並把session序列化到硬盤文件中。
3. 把序列化過的session置爲不可用,並重置session中的所有屬性。
PersistentManager 源碼分析
1. session 鈍化
通過 ContainerBase.startInternal() -> threadStart() 開啓一個線程,定時的輪詢所有的session,把長時間不使用(或者超出最大數量等)的session鈍化到硬盤上。
threadStart()
每隔backgroupProcessorDelay時間輪詢處理session。
processPersistenceChecks()
PersistentManagerBase.processExpires() -> processPersistenceChecks()
Tomcat只是在下面三種情況會將Session通過Store保存起來:
1. 當Session的空閒時間超過minIdleSwap和maxIdleSwap時,會將Session換出
2. 當Session的空閒時間超過maxIdleBackup時,會將Session備份出去
3. 當Session總數大於maxActiveSession時,會將超出部分的空閒Session換出
下面只分析下第一種情況的源碼processMaxIdleSwaps() 方法
processMaxIdleSwaps()
1. 判斷Session的空閒時間超過minIdleSwap和maxIdleSwap值。
2. 如果超過則通過 swapOut() 方法把session鈍化到硬盤上。
swapOut() 方法
1. 通過passivate() 方法調用web.xml 中註冊的HttpSessionActivationListener事件(同StandardSession)
2. 調用writeSession() 方法把session鈍化到指定的地方
3. 從sessions 中把session移除
4. 重置session,等待垃圾收集器回收此session。
writeSession()
調用store把session存儲到指定的地方,如下面的配置,是把session鈍化到硬盤文件中。
1 | <store classname= "org.apache.catalina.session.FileStore" directory= "sessionDir" > </store> |
2. session 活化
1. 當請求中獲取session時,先從調用findSession() 從內存sessions 中查找。
2. 如果內存中找不到 則調用 swapIn() 方法,進行查找,判斷該session是否鈍化了,如果鈍化則把該session活化加載到內存。
swapIn() 方法
爲當前查找的session設置一個lock。
1. 雙重檢查,在鎖中再次判斷sessions中是否有此session。
2. 從store中加載session。
3. 如果store 有此session 並判斷該session是否過期,並做處理
1. 通過tellNew() 調用 web.xml 中註冊HttpSessionListener的事件
2. 把session添加到sessions 集合中。
3. 通過activate()方法調用web.xml中註冊的HttpSessionActivationListener事件
4. 最後把該session相關的鎖,刪除。