springboot程序假死?

我在windows server上部署了一个springboot的jar包。启动命令如下:
@echo off
javaw -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump.hprof -Dapp.name="largeSceen" -Dfile.encoding=utf-8 -Xms10240m -Xmx20480m -XX:MaxDirectMemorySize=4g -jar C:\Users\Administrator\Desktop\大屏项目\largeScreen-1.0.0.jar > server.log 2>&1
exit
jar包内部有application.yml, jar包外部同级目录也有application.yml来覆盖数据库连接。
昨天出现了一个问题,数据库宕机了一点时间,一直连不上。
今天查看前端,发现数据库连接到了内部的application.yml的数据库连接。
并且使用jps找不到java进程。
但是使用netstat -ano |findstr 11011(jar的端口) 可以找到进程
此外server.log 没有继续写入日志,内部的logback配置也没有生效,没有写入到app.log
请问这是什么原因?

阅读 523
1 个回答
✓ 已被采纳

应用程序可能在数据库宕机时出现了异常,但没有完全崩溃,这就是典型的"僵尸"状态。这种情况下,进程虽然还在运行(所以端口仍被占用),但实际上已经不再正常工作了。

当你的数据库恢复后,这个"僵尸"进程试图重新连接数据库,但因为它已经处于异常状态,可能回退到了使用jar包内部的配置而不是外部的覆盖配置。

核心在于:

  1. jps命令找不到java进程(进程可能已不被Java管理系统正常识别,僵死状态大部分识别不出来)
  2. netstat仍然显示端口被占用(进程仍然存在于操作系统中)
  3. 日志不再更新(进程无法正常执行IO操作,比如在出现异常时导致没有释放等)
  4. 使用了内部而非外部的数据库配置(配置重载机制失效)

可以参考一下方法解决:

  1. 找到这个进程:tasklist /fi "pid eq 端口对应的PID"
  2. 强制结束它:taskkill /F /PID 对应的PID号
  3. 重启应用

但是需要注意的是:为了防止将来再次发生这种情况,你可以:

  1. 在启动脚本中添加自动重启的逻辑
  2. 设置数据库连接的重试参数
  3. 考虑使用Windows服务而不是简单的批处理脚本来管理应用程序
  4. 还有就是检查源码中是否有出现异常未进行资源释放导致出现僵尸进程

这类问题在生产环境中很常见,特别是当依赖服务(如数据库)暂时不可用时。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题