首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

解決 Tomcat 重啟報錯:Exception loading sessions from persistent storage

     編輯:Java 相關知識

Tomcat 非正常關閉後重啟,常見嚴重錯誤:Exception loading sessions from persistent storage。本文解析根因、提供標準關閉方案與禁用持久化配置,徹底消除啟動報錯。

一、錯誤現象與根因

嚴重: Exception loading sessions from persistent storage
java.io.EOFException
    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2738)
    ...

根因:Tomcat 預設啟用 Session 持久化(StandardManager),關閉時將內存 Session 序列化到 work/Catalina/localhost//SESSIONS.ser。非正常關閉(kill -9、崩潰、斷電)導致文件寫入不完整或損壞,啟動時反序列化失敗拋出 EOFException/StreamCorruptedException。

影響:僅影響 Session 恢復,用戶需重新登錄,**不影響應用業務功能**。

二、方案一:標準化關閉流程(治本)

  1. 使用 shutdown.sh/catalina.sh stop:發送 SIGTERM,Tomcat 執行 LifecycleListener 正常持久化 Session。
  2. 避免 kill -9:強制終止跳過 JVM 關閉鉤子,導致文件損壞。
  3. 系統服務管理:Systemd 配置 KillSignal=SIGTERM、TimeoutStopSec=60 確保優雅停機。

三、方案二:禁用 Session 持久化(治標,推薦生產環境)

修改 conf/server.xml 或 conf/context.xml,在 <Context> 節點添加 <Manager> 配置:

1. 完全禁用持久化(最簡單)

<Context ...>
    <Manager className="org.apache.catalina.session.PersistentManager" 
             saveOnRestart="false" />
</Context>

2. 或使用標準 Manager 禁用持久化

<Context ...>
    <Manager className="org.apache.catalina.session.StandardManager" 
             pathname="" />
</Context>

pathname="" 表示不生成 SESSIONS.ser 文件。

3. 生產環境推薦:Redis 集群化 Session(高可用)

<!-- 需引入 tomcat-redis-session-manager 依賴 -->
<Context ...>
    <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
             host="redis-host" port="6379"
             database="0" maxInactiveInterval="1800" />
</Context>
  • Session 存儲於 Redis,多實例共享,重啟無感、擴容無憂。
  • 解決單機持久化文件損壞、集群 Session 不一致兩大痛點。

四、驗證與清理

  1. 修改配置後重啟 Tomcat,觀察啟動日誌無 Exception loading sessions。
  2. 刪除舊的損壞文件:rm -rf work/Catalina/localhost/*/SESSIONS.ser。
  3. 若保留持久化,定期清理過期 Session 文件防止磁盤佔用。

五、進階:自定義 Manager 實現優雅降級

若業務強依賴 Session 恢復,可繼承 StandardManager 重寫 load() 方法,捕獲異常時記錄警告並返回空 Session 集合,而非拋出異常中斷啟動:

public class RobustManager extends StandardManager {
    @Override
    public void load() throws ClassNotFoundException, IOException {
        try {
            super.load();
        } catch (Exception e) {
            log.warn("Session 持久化文件損壞,忽略並啟動空 Session 池", e);
            sessions.clear();
        }
    }
}

在 context.xml 中指定 className="com.example.RobustManager"。

總結

方案適用場景優點缺點
標準關閉所有環境保留 Session、零配置依賴運維規範,不可控
禁用持久化無狀態服務、可接受重新登錄簡單徹底、零報錯重啟 Session 丟失
Redis Session生產集群、高可用要求Session 不丟、跨實例共享引入外部依賴、增加複雜度
自定義 Manager需保留 Session 但容忍損壞啟動不阻塞、兼容現有邏輯需開發維護、邊界情況需測試

推薦策略:開發/測試環境禁用持久化,生產環境上 Redis Session,徹底告別啟動報錯與 Session 丟失困擾。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved