文档目录

问题说明

本文用于排查承载ZCenter的虚拟机重启后,一个或多个ZCenter服务持续出现“启动、健康检查失败、退出或被终止、再次启动”的循环。该现象通常与虚拟机资源不足、磁盘读写延迟、依赖服务尚未恢复或外部健康检查/进程管理器重启策略有关。

现象

  • 重启承载ZCenter的虚拟机后,管理页面长时间无法访问,或间歇性返回502/503。
  • Java进程、容器或Pod反复创建和退出,进程PID持续变化。
  • systemd日志出现 Main process exited、Start request repeated too quickly、Failed with result 或 start-limit-hit。
  • Docker环境出现 Restarting、unhealthy、CrashLoopBackOff、Liveness probe failed、Readiness probe failed、OOMKilled 等状态。
  • ZCenter日志重复出现服务启动日志,但始终未进入稳定运行状态;还可能出现数据库、Redis、RabbitMQ、Nacos连接超时或Flyway启动失败。
  • 主机存在高I/O等待、内存不足、频繁Swap、CPU持续满载或磁盘空间不足。

适用环境

  • 产品:ZCenter
  • 版本:5.1.0
  • 组件:ZCenter各Java服务、Caddy、Gateway、Nacos、MariaDB/MySQL、Redis、RabbitMQ
  • 部署形态:承载于虚拟机上的systemd、Docker或Kubernetes部署

可能原因

该现象可能由以下一种或多种原因导致:

  1. 磁盘读写性能不足:虚拟机重启后多个服务同时读取JAR、写日志、初始化数据库连接或执行Flyway,磁盘高延迟导致服务在健康检查时限内无法就绪。
  2. CPU配置不足或CPU竞争:现场案例中,分配CPU低于16核时可能出现启动时间过长。16核是现场排障经验值,不代表当前资料已确认的ZCenter 5.1.0官方最低配置。
  3. 内存不足或Swap抖动:多个Java服务并发启动时,宿主虚拟机可用内存不足,可能触发频繁GC、Swap或操作系统OOM终止进程。内存应使用GB衡量,不能写成“低于16核”。
  4. 依赖服务恢复较慢:MariaDB/MySQL、Redis、RabbitMQ或Nacos尚未可用,ZCenter服务连接超时、注册失败或初始化失败。
  5. 健康检查宽限时间不足:外部systemd、Docker、Kubernetes或运维平台在服务完成初始化前判定为不健康并重启进程。
  6. 启动顺序不合理:ZCenter业务服务与数据库、Redis、RabbitMQ、Nacos同时启动,业务服务先于依赖服务进入初始化。
  7. 磁盘容量、inode或文件系统异常:磁盘已满、inode耗尽、文件系统只读或存在I/O错误,导致日志、上传目录或数据库无法正常读写。
  8. 数据库迁移或配置错误:Flyway校验失败、数据库连接失败、Redis密码错误等确定性错误会导致每次重启都在相同位置失败,此类情况仅扩容资源不能解决。

排查步骤

按以下顺序检查,先确认“谁在重启服务”,再判断是否为资源或依赖问题。

1. 确认循环启动的对象和重启来源

  • 检查项:确认是整个虚拟机反复重启,还是Java进程、容器或Pod被外部管理器重启。
  • Docker环境:
  docker ps -a
  docker inspect -f '{{.Name}} restart={{.HostConfig.RestartPolicy.Name}} count={{.RestartCount}} state={{json .State}}' <container>
  docker logs --since 2h <container>
  • 预期结果:明确服务退出码、终止信号、重启策略以及健康检查失败记录。
  • 异常处理:如果没有应用退出堆栈,而是外部健康检查主动终止服务,继续检查健康检查目标、超时和启动宽限时间;如果存在固定异常堆栈,优先按异常处理。

2. 检查CPU、内存和OOM

  • 命令:
  uptime
  free -m
  vmstat 1 10
  ps -eo pid,ppid,stat,etime,%cpu,%mem,rss,vsz,cmd --sort=-%cpu
  ps -eo pid,ppid,stat,etime,%cpu,%mem,rss,vsz,cmd --sort=-%mem
  dmesg -T --level=err,warn
  • 预期结果:启动期间CPU仍有余量,可用内存稳定,无持续Swap换入换出,也无 Out of memory、Killed process、OOMKilled 或退出码137。
  • 异常处理:
  • CPU持续满载且服务仅表现为启动超时:结合业务规模和正式部署规格增加CPU,或错峰启动服务。现场案例可将CPU低于16核作为重点核查项,但不能替代正式容量评估。
  • 可用内存过低、频繁Swap或发生OOM:根据各Java进程实际RSS、JVM堆配置和正式部署规格扩容内存或调整进程资源限制。
  • 不要仅增大健康检查超时掩盖OOM或持续CPU饱和。

3. 检查磁盘容量和读写延迟

  • 命令:
  df -hT
  df -ih
  iostat -xz 1 10
  dmesg -T --level=err,warn
  • 检查项:重点观察 %util、await、%iowait、磁盘剩余空间和inode。
  • 预期结果:磁盘空间和inode充足,启动期间无持续高I/O等待,无文件系统或块设备错误。
  • 异常处理:
  • 磁盘容量或inode不足时,按运维规范清理非必要文件或扩容,不能直接删除数据库和应用关键目录。
  • await、%util和%iowait持续过高时,检查底层存储性能、虚拟磁盘类型、宿主机存储竞争和快照链。
  • 日志中出现 No space left on device、Read-only file system、I/O error 或日志文件创建失败时,先恢复文件系统和磁盘状态。

4. 检查依赖服务和启动顺序

  • 检查端口:
  ss -lntp | grep -E ':(3306|5672|6379|8848|8100|8200)\b'
  • 检查Nacos:
  curl -v --max-time 10 http://<nacos-host>:8848/nacos/actuator/health
  • 检查Redis:
  redis-cli -h <redis-host> -p <redis-port> --askpass PING
  • 检查项:确认MariaDB/MySQL、Redis、RabbitMQ、Nacos已完成恢复,再检查ZCenter服务是否成功启动和注册。
  • 预期结果:依赖端口可达、认证成功,Gateway能发现Portal、Base及业务服务实例。
  • 异常处理:依赖尚未就绪时,先按部署规范恢复依赖服务,再启动ZCenter业务服务;不要通过不断重启全部服务尝试碰运气。

5. 检查服务启动日志

  • 日志位置:通常为运行目录下的 logs/zscmp.log,实际路径以部署参数为准。
  • 建议搜索:
  Application run failed
  OutOfMemoryError
  Killed process
  Flyway
  checksum mismatch
  HikariPool
  Unable to obtain connection
  Connection refused
  Redisson
  Nacos
  No space left on device
  I/O error
  Permission denied
  • 判断方法:
  • 每次都在相同异常堆栈处退出,优先处理该确定性错误。
  • 每次失败位置不同,且伴随高CPU、低内存或高I/O等待,优先处理资源瓶颈。
  • 服务本身持续运行,但被健康检查终止,继续检查第6步。

6. 检查健康检查和重启策略

  • 检查项:确认健康检查访问的是目标服务直接端口,而不是被Gateway明确拦截的 /actuator/** 路径。
  • 注意:Gateway配置会对经过Gateway的 /actuator/** 返回404,因此外部健康检查若错误地访问Gateway的该路径,可能把正常服务判定为异常。
  • 检查健康检查的初始延迟、超时、周期、失败阈值和启动探针,并与实际启动耗时比较。
  • 异常处理:在已经排除资源不足和确定性启动错误后,可适当延长启动宽限时间或增加失败阈值;不要直接永久关闭健康检查。

7. 收集支持信息

  • 虚拟机CPU、内存、Swap、磁盘容量、磁盘类型和故障发生时的I/O指标。
  • systemd/Docker/Kubernetes的重启策略、健康检查配置、退出码和重启次数。
  • 从虚拟机开机到服务稳定或再次退出的完整时间线。
  • ZCenter、数据库、Redis、RabbitMQ、Nacos和Caddy在同一时间窗口的日志。
  • 最近的虚拟机规格、磁盘、JVM参数、服务编排或健康检查配置变更。

处理方式

根据排查结论选择对应处理,不建议同时修改多个变量:

  1. 磁盘I/O不足:迁移到满足性能要求的存储、减少宿主机存储竞争、处理过长快照链,并确保日志和数据库目录所在磁盘状态正常。
  2. CPU不足:按业务规模和正式部署规格增加CPU;现场已观察到CPU低于16核时启动可能过慢,该数值仅作为重点检查条件。
  3. 内存不足:根据实际RSS、JVM堆和OOM记录扩容内存或修正容器资源限制。当前代码库未提供可作为官方结论的最低内存数值。
  4. 依赖服务恢复较慢:调整启动顺序,确保数据库、Redis、RabbitMQ和Nacos就绪后再启动ZCenter服务。
  5. 健康检查过早:在确认服务最终可正常启动后,根据实测启动耗时调整初始延迟、启动宽限时间、超时和失败阈值。
  6. 确定性配置或迁移错误:按日志修复数据库连接、Redis认证、Nacos注册或Flyway问题,不能仅通过扩容解决。

验证方法

  • 重启验证:在维护窗口按部署规范重启承载ZCenter的虚拟机,确认所有依赖和ZCenter服务只启动一次并持续稳定运行。
  • 进程验证:观察systemd、容器或Pod至少一个完整健康检查周期,重启次数不再增加。
  • 资源验证:启动期间CPU、可用内存、Swap和磁盘I/O处于可接受范围,无OOM和文件系统错误。
  • 端口验证:8100、8200及依赖端口按部署拓扑正常监听,Gateway能够发现业务服务。
  • 功能验证:完成登录、访问资源列表和一次受控资源同步,页面不再返回502/503。
  • 日志验证:服务日志不再重复出现启动序列,也不再出现健康检查失败、依赖连接超时或固定启动异常。

风险与回滚

  • 调整CPU、内存、磁盘或虚拟机规格通常需要维护窗口,操作前确认业务影响和虚拟机回退方案。
  • 调整健康检查过于宽松可能延迟真实故障发现;应保留原配置并基于实测启动耗时设置,而不是关闭健康检查。
  • 修改服务启动顺序或重启策略前应记录原systemd、Docker或Kubernetes配置,异常时恢复原配置。
  • 不要通过删除数据库、清空Redis、删除全部日志或连续强制重启服务处理循环启动。

补充信息

重启承载 ZCenter 的虚拟机后服务持续循环启动,如何排查? | 故障排查 · KB | ZStack 资源中心