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 示例。

相关推荐
Wx-bishekaifayuan39 分钟前
Springcloud中学在线学习平台58883-计算机课程设计、毕业设计
java·vue.js·spring boot·学习·spring·spring cloud·课程设计
JavaEdge.1 小时前
Redis 连接断开后的自动重连操作
spring boot·redis·后端·lettuce·tcp keepalive
EatFan10 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
凤山老林16 小时前
Spring Boot 集成 iText 7 实现动态 PDF 生成与电子签章:合同、报表场景实战
spring boot·后端·pdf·itext7·电子签章
卓怡学长16 小时前
w204基于springbo旅行社签证代理服务系统
java·spring boot·spring·intellij-idea
qwfy16 小时前
我要用 AI-native 架构,从零重建一套制造业 ERP/MES
vue.js·spring boot·架构
vipxieliang16 小时前
ValidX 在微服务架构中的验证策略
java·spring boot
❀͜͡傀儡师16 小时前
20 年沉淀,CAS 8.0 重新定义企业级 SSO:适配 JDK 25 与 Spring Boot 4.1
java·开发语言·spring boot
牧瀬クリスだ17 小时前
Spring统一功能处理
java·spring boot·spring·状态模式
Dreams_l18 小时前
基于SpringBoot实现的抽奖系统(一)
java·spring boot·后端