Spring Boot 服务挂了却没重启?先分清 systemd 的三次判断

线上有个 Spring Boot 服务退出后没有再起来,第一反应通常是补一句 Restart=always。我见过这么改的,结果是发版时正常停掉的进程也被拉回来了,现场更乱。

systemd 不是看到进程没了就无脑重启。它至少要过三道判断:这次退出算不算失败,重启次数有没有撞限额,当前追踪到的到底是不是你以为的那个主进程。

先看退出为什么没有被算成失败

对常驻服务,Restart=on-failure 通常是比 always 更稳的默认选择。systemd 的官方说明也把它列为长运行服务的推荐项。

但它只会在这些情况重启:

  • 进程返回非零退出码
  • 进程异常被信号终止
  • 服务启动或运行超时

退出码是 0,或者是有意停止的 SIGTERM、SIGINT,都不属于它要补救的故障。

所以排查时别只盯着「进程没了」。有些启动脚本把 Java 异常吃掉以后又 exit 0,systemd 会认为这次服务正常结束。手动执行 systemctl stop 后不自动拉起也完全正常。

先看这一组信息:

bash 复制代码
systemctl status demo-api
systemctl show demo-api -p Result -p ExecMainCode -p ExecMainStatus -p NRestarts
journalctl -u demo-api -b --no-pager -n 100

我一般先找两件事:最后一次退出的 code 和 status 是什么,日志里失败发生在 Java 进程里还是发生在启动命令本身。

重启策略生效了,也可能被限频拦住

服务连续崩溃时,systemd 会遵守 RestartSec= 的等待时间,但不会无限次地拉起。它还会按 StartLimitIntervalSec= 和 StartLimitBurst= 做启动限频。

看到 start-limit-hit,不要急着把阈值调大。那只是在让错误更快刷屏。先把导致崩溃的配置、依赖或端口问题修掉,之后再清理失败状态:

bash 复制代码
sudo systemctl reset-failed demo-api
sudo systemctl restart demo-api

下面这份 unit 文件适合先把行为讲清,不是照抄到所有机器上的万能模板:

ini 复制代码
[Unit]
Description=demo-api
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
User=app
WorkingDirectory=/srv/demo-api
Type=exec
ExecStart=/usr/bin/java -jar /srv/demo-api/app.jar
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

这里的 60 秒和 3 次只是一个明确的保护边界。实际值要看服务启动成本、依赖恢复速度和报警承受能力。把 RestartSec=0 当成「恢复更快」往往不是好事,它会让崩溃循环更快撞上限频。

Type=exec 解决的不是应用启动失败

很多 unit 文件完全不写 Type=,默认是 simple。对于长期运行的 Java 进程,Type=exec 有个很实在的好处:可执行文件不存在、用户不存在这类 execve 之前的启动错误,systemd 能更可靠地记录为启动失败。

但别把它神化。JAR 已经被 Java 拉起来,应用随后因为数据库连不上而退出,这仍然要靠退出状态和日志来判断。它不会替 Spring Boot 判断「业务已就绪」。

面试里怎么收这题

被问「为什么不用 Restart=always」,我会先说清目标:守住异常退出,不干预运维的正常停止。

然后补一句,真正可靠的配置不只是一个 Restart。要同时确认退出状态能反映失败,给重启留出间隔,再让限频把持续崩溃挡住。这样面试官继续问服务为什么没拉起,才有具体的排查顺序,不会只剩一句「加个重启策略」。

资料核对:systemd.service(5)、systemd.unit(5)、Spring Boot Reference Documentation 的 Linux systemd service 示例。

相关推荐
杨凯凡几秒前
Spring Boot 文件上传怎么做才安全?流式落盘、路径校验与数据库一致性实战
java·spring boot·文件上传·后端安全·数据库一致性
howard20051 小时前
Spring Boot 版成绩统计分析
spring boot·成绩统计分析
Yyyyyy~14 小时前
【Java】Day4Web基础知识
java·spring boot
逆回18 小时前
升级 Boot 4 后,我的 mock 全红了
spring boot
学长毕设1 天前
基于SpringBoot的野生动物公益保护平台设计与实现-附源码
java·spring boot·后端
她的男孩1 天前
三人会签只批了一个就往下走:Forge Admin 把 all / any / ratio 写成 completionCondition
spring boot·低代码·工作流引擎
vipxieliang1 天前
ValidX vs 手写验证代码:开发效率对比实测
java·spring boot·后端
vipxieliang1 天前
虚拟线程与 GraalVM:Spring Boot 3.x 云原生性能跃迁
java·spring boot·后端
头发还在的女程序员1 天前
基于 Spring Boot + Vue 3 + uni-app 的灵活用工系统:四端架构与业务流程设计
vue.js·spring boot·uni-app·灵活用工·灵工系统
CoderYanger1 天前
Java EE 进阶:8.MyBatis 操作数据库(入门)(第二弹)
java·数据库·spring boot·spring·面试·java-ee·mybatis