当前位置: 首页 > news >正文

一次生产环境 Tomcat 7 + JDK 7 应用启动失败的完整排查与修复实录 - 指南

一次生产环境 Tomcat 7 + JDK 7 应用启动失败的完整排查与修复实录 - 指南

文章目录

  • 一次生产环境 Tomcat 7 + JDK 7 应用启动失败的完整排查与修复实录
    • 一、问题初现:看似成功,实则崩溃
    • 二、第一步:解决端口冲突(表面问题)
      • 定位占用进程
      • ️ 强制清理
      • ✅ 验证重启
    • 三、第二步:修复内存泄漏(根本问题)
      • 1. JDBC 驱动未注销
      • 2. MySQL 后台线程未停
      • 3. Quartz 工作线程泄漏(最严重)
      • ️ 解决方案:添加全局销毁监听器
    • 四、第三步:修复 Ehcache RMI 集群配置
      • ✅ 正确做法
      • 开放防火墙
    • 五、其他优化项
      • 1. 解决 SLF4J 多绑定冲突
      • 2. 移除 WEB-INF/lib 中的 servlet-api.jar
    • 六、最终验证
    • 七、经验总结

一次生产环境 Tomcat 7 + JDK 7 应用启动失败的完整排查与修复实录

环境:CentOS 7 + Tomcat 7.0.96 + JDK 1.7.0_80 + Ehcache 2.6 + Memcached
应用:Spring MVC 项目 /dhmall,含 Quartz 定时任务、Druid 数据源、RabbitMQ、银联支付 SDK
问题现象:Tomcat 启动后立即崩溃,报 Address already in use,伴随大量内存泄漏警告

本文将完整复盘从日志分析、端口冲突解决到资源泄漏修复的全过程,为同类老旧 Java 系统提供排错参考。


一、问题初现:看似成功,实则崩溃

首次查看日志时,被这行迷惑:

INFO: Server startup in 23868 ms

但紧接着出现致命错误:

SEVERE: StandardServer.await: create[localhost:8088]:
java.net.BindException: Address already in use

随后 Tomcat 自动进入 shutdown 流程,并暴露出一系列严重警告:

SEVERE: The web application [] registered the JDBC driver [...] but failed to unregister it
SEVERE: The web application [] appears to have started a thread named [schdulerFactory_Worker-1]...

结论:这不是简单的“端口占用”,而是 残留进程 + 资源泄漏 的复合型故障。


二、第一步:解决端口冲突(表面问题)

定位占用进程

# 查找占用 8088 或 8005 端口的进程
lsof -i :8088
lsof -i :8005
# 输出示例
java    12345 user ... /apache-tomcat-7.0.96/...

️ 强制清理

kill -9 12345
# 再次检查确保无残留
netstat -tulnp | grep -E '8088|8005'

经验:在频繁部署或异常断电后,Tomcat 进程常“假死”残留,务必手动清理。

✅ 验证重启

/data/soft/apache-tomcat-7.0.96/bin/startup.sh
tail -f logs/catalina.out

此时 Tomcat 成功启动,HTTP 服务可访问。但隐患仍在


三、第二步:修复内存泄漏(根本问题)

尽管应用能运行,但每次重启都会留下“垃圾”,长期将导致 Metaspace OOM。日志中三大泄漏点:

1. JDBC 驱动未注销

SEVERE: ... registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister

2. MySQL 后台线程未停

SEVERE: ... thread named [MySQL Statement Cancellation Timer] ...

3. Quartz 工作线程泄漏(最严重)

SEVERE: ... thread named [schdulerFactory_Worker-1] ... memory leak

️ 解决方案:添加全局销毁监听器

创建 AppCleanupListener.java

package com.dhmall.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import net.sf.ehcache.CacheManager;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class AppCleanupListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
// 1. 关闭 Quartz 调度器
try {
Scheduler scheduler = (Scheduler) ctx.getBean("schdulerFactory");
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown(true); // 等待任务完成
}
} catch (Exception e) {
e.printStackTrace();
}
// 2. 关闭 Ehcache(如有集群,会自动注销 RMI)
try {
CacheManager.getInstance().shutdown();
} catch (Exception e) {
e.printStackTrace();
}
// 3. (可选)显式注销 JDBC 驱动(新版通常自动处理)
// DriverManager.deregisterDriver(...);
}
@Override
public void contextInitialized(ServletContextEvent sce) {
// 初始化逻辑(如设置 RMI hostname)
System.setProperty("java.rmi.server.hostname", "172.26.100.204");
}
}

web.xml 中注册:

<listener>
<listener-class>com.dhmall.listener.AppCleanupListener</listener-class>
</listener>

效果:应用停止时,Quartz 线程池优雅关闭,Ehcache 断开 RMI 连接,JDBC 驱动被清理。


四、第三步:修复 Ehcache RMI 集群配置

原配置存在致命错误:

<cacheManagerPeerListenerFactoryproperties="hostName=localhost, port=40001, ..." />

hostName=localhost 导致其他节点无法连接!

✅ 正确做法

  1. 移除 hostName 配置
  2. 通过 JVM 参数指定对外 IP

tomcat/bin/setenv.sh(若无则新建)中添加:

export CATALINA_OPTS="$CATALINA_OPTS -Djava.rmi.server.hostname=172.26.1.2"

ehcache.xml 简化为:

<cacheManagerPeerListenerFactoryclass="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"properties="port=40001, socketTimeoutMillis=2000" />

开放防火墙

firewall-cmd --permanent --add-port=40001/tcp
firewall-cmd --reload

五、其他优化项

1. 解决 SLF4J 多绑定冲突

日志中:

SLF4J: Class path contains multiple SLF4J bindings.

pom.xml 中排除冗余绑定:

<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>

2. 移除 WEB-INF/lib 中的 servlet-api.jar

validateJarFile(.../servlet-api-2.5.jar) - jar not loaded.

该 JAR 应由 Tomcat 提供,应用中不应包含。


六、最终验证

  1. 正常启动:无 BindExceptionServer startup in XXX ms 后持续运行
  2. 无泄漏警告:重启时不再出现 SEVERE: ... memory leak
  3. 集群同步:多节点环境下缓存更新实时生效
  4. 外部可访问curl http://服务器IP:8088/dhmall/xxx 返回正常

七、经验总结

问题类型教训
端口冲突永远先查 lsof,不要被“startup”迷惑
线程泄漏所有后台线程(Quartz/Ehcache/Timer)必须显式关闭
RMI 配置hostName=localhost 是集群最大陷阱
老旧技术栈JDK 7 + Tomcat 7 已 EOL,建议尽快升级

最后忠告:对于仍在使用 JDK 7/Tomcat 7 的系统,请务必建立完善的启停脚本和健康检查机制。技术债终需偿还,但在此之前,我们仍要守护好每一行 legacy code 的稳定运行。

http://www.gsyq.cn/news/110486.html

相关文章:

  • LobeChat本地安装详细教程
  • 2025年年终柳州管道疏通推荐:综合排名比较与真实用户评测报告 - 十大品牌推荐
  • 2025年起名老师联系方式汇总:全国资深专家联系通道与专业起名服务指引 - 品牌推荐
  • 2025广东最新AI搜索/GEO/AI营销服务推荐!东莞等企业智能转型优选方案发布,技术赋能驱动数字化升级 - 全局中转站
  • 2025年公司取名公司联系方式汇总: 全国主要服务机构官方联系方式及专业合作指引 - 品牌推荐
  • Jenkins备份及回滚方式
  • 2025年年终合肥管道疏通推荐:权威榜单TOP5及用户真实评价汇总 - 品牌推荐
  • 家用制氧机选哪个好?老人用、术后用、高原用制氧机真实评测与选购指南 - 速递信息
  • 2025年年终柳州管道疏通推荐:专业排行解析与多维度服务对比指南 - 十大品牌推荐
  • 详细介绍:3D空间表征基础
  • LobeChat能否生成SQL语句?数据库查询助手上线
  • MTS AI智能聚合公链正式上线
  • 「直通」英伟达,蓝思科技补齐AI算力布局又一块拼图
  • PaddlePaddle训练任务中断恢复:借助git版本控制系统还原状态
  • ComfyUI缺少Manager?手把手教你安装
  • 2025年空气加热器生产厂家排名,精选空气加热器生产企业排名 - 工业推荐榜
  • 使用 Docker Compose 部署 LobeChat 数据版
  • CMAC和HMAC算法的区别
  • ESP32能否运行GPT-SoVITS?边缘设备适配性分析
  • Qwen3-VL-30B-FP8:高性能多模态模型量化新突破
  • Qwen-Image-Edit-2509能上手机吗?云端+端侧全解析
  • 用Seed-Coder-8B-Base智能生成K8s配置
  • 140亿参数Wan2.2-T2V-A14B本地部署全解析
  • LobeChat能否提供溯源链接?信息可信度提升
  • 2025年想建立外贸独立站有什么途径?
  • MemTest64官网下载和安装图文教程(附安装包,超详细)
  • 基于PaddlePaddle的视觉模型训练实战:从Docker安装到GPU算力调用
  • 湖南网安基地:国家级平台如何用实战教学让你快速入行网络安全
  • 腾讯企业邮箱服务商选择指南:3步选出最适合的方案 - 品牌2026
  • Diskinfo下载官网工具分析TensorRT存储瓶颈