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

优雅!通过编程方式重启 Spring Boot 应用的 3 种方案

优雅!通过编程方式重启 Spring Boot 应用的 3 种方案

场景:

  1. 动态刷新配置后希望热重启
  2. 升级 JAR 后无停机替换
  3. 运行中检测到致命错误,需要自恢复

本文给出三种经过生产验证的方案,全部 零外部依赖仅依赖 Actuator,可按场景自由取舍。


方案总览

方案触发位置是否关闭旧进程是否零停机依赖
SpringApplication.restart()同 JVMSpring Cloud Context
② Actuator restart 端点HTTP/SSHActuator
③ 自托管脚本 + 优雅关闭新 JVM

方案 1:编程式 RestartEndpoint(最轻量)

需要 spring-cloud-starter 或单独引入 spring-cloud-context

1.1 依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter</artifactId>
</dependency>

1.2 一行代码即可重启

@RestController
@RequiredArgsConstructor
public class RestartController {private final RestartEndpoint restartEndpoint;   // 来自 spring-cloud@PostMapping("/restart")public String restart() {Executors.newSingleThreadExecutor().submit(() -> restartEndpoint.restart()); // 异步,防止阻塞当前线程return "restarting...";}
}

1.3 特点

  • 无进程切换,同 JVM 热刷新
  • 会重新执行整个 SpringApplication.run,但 不会退出 JVM
  • 适用于配置热更新代码热替换(DevTools)

方案 2:Actuator /actuator/restart(运维最爱)

2.1 引入 Actuator & 暴露端点

management:endpoints:web:exposure:include: restart,health,infoendpoint:restart:enabled: true

2.2 一键重启

curl -X POST http://localhost:8080/actuator/restart

2.3 进阶用法

  • 脚本化

    #!/bin/bash
    PID=$(pgrep -f myapp.jar)
    curl -s -X POST http://localhost:${MGMT_PORT:-8080}/actuator/restart
    # 等待健康 UP
    while [ "$(curl -s http://localhost:${MGMT_PORT:-8080}/actuator/health | jq -r .status)" != "UP" ]; dosleep 1
    done
    echo "restart done"
    
  • 灰度重启
    在负载均衡摘除节点 → 调 /restart → 健康检查 → 重新挂载。


方案 3:自托管脚本优雅重启(生产终极方案)

适用于 升级 JAR、JDK 参数变化 等需要真正 进程替换 的场景。

3.1 关闭钩子优雅停机

@SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication app = new SpringApplication(App.class);app.addListeners((ApplicationListener<ContextClosedEvent>) e -> {// 关闭线程池、MQ、连接池GracefulShutdown.destroy();});app.run(args);}
}

3.2 自动重启脚本(restart.sh)

#!/bin/bash
APP_NAME=myapp
JAR_PATH=/opt/apps/${APP_NAME}.jar
PID_FILE=/var/run/${APP_NAME}.pid
JAVA_OPTS="-Xms512m -Xmx512m"# 1. 优雅关闭
if [ -f $PID_FILE ]; thenPID=$(cat $PID_FILE)kill -15 $PIDfor i in {1..30}; dokill -0 $PID 2>/dev/null || breaksleep 1donekill -9 $PID 2>/dev/null || true
fi# 2. 启动新进程
nohup java $JAVA_OPTS -jar $JAR_PATH > /dev/null 2>&1 &
echo $! > $PID_FILE

3.3 在应用内触发脚本

@RestController
public class UpgradeController {@PostMapping("/upgrade")public void upgrade() throws IOException {Runtime.getRuntime().exec("./restart.sh");}
}

选型与最佳实践

场景推荐方案
仅刷新配置方案 1
运维/CI 一键重启方案 2
升级 JAR、JDK 参数变化方案 3
高可用集群方案 2 + 方案 3 结合,逐台灰度

小结

  • 方案 1 最轻量,一行代码搞定同 JVM 热重启。
  • 方案 2 最友好,运维通过 HTTP 即可重启,零登录服务器。
  • 方案 3 最通用,任何升级、回滚都可优雅完成。
http://www.dtcms.com/a/294321.html

相关文章:

  • Apache PDFBox深入实践
  • python学智能算法(二十九)|SVM-拉格朗日函数求解中-KKT条件
  • PHP语法高级篇(五):回调函数与异常处理
  • Ansible 变量指南:声明、优先级、作用域与最佳实践(一)
  • Jquery、Vue 、Ajax、axios、Fetch区别
  • Ansible在配置管理中的应用
  • ffmpeg rtsp 丢包处理
  • SSH公钥认证连接过程
  • Linux 进程与服务管理~进程基础、进程查看、进程控制、服务管理、开机启动​​
  • 纯CPU场景下C++的分布式模型训练框架设计思路
  • 2025.7.20 文献阅读-基于深度神经网络的半变异函数在 高程数据普通克里格插值中的应用
  • go语言数据结构与排序算法
  • 【C++】C++ 的入门知识2
  • Android 持久化存储原理与使用解析
  • MATLAB | 绘图复刻(二十二)| 带树状图的三角热图合集
  • 个性化网页计数器
  • C 语言介绍
  • 【数据结构】二叉树的链式结构--用C语言实现
  • 嵌入式linux下的NES游戏显示效果优化方案:infoNES显示效果优化
  • 我用EV-21569-SOM评估来开发ADSP-21569(十三)-SigmaStudio Plus做开发(4)
  • Web前端开发:JavaScript遍历方法详解与对比
  • 安全防护-FCW
  • [HarmonyOS] HarmonyOS LiteOS-A 设备开发全流程指南
  • Linux第三天Linux基础命令(二)
  • 服务器对kaggle比赛的数据集下载
  • SAP-ABAP:SELECT语句验证字段和验证方法详解
  • OSPF路由协议——上
  • 28. 找出字符串中第一个匹配项的下标
  • vue3中el-table表头筛选
  • Flink 状态管理设计详解:StateBackend、State、RocksDB和Namespace