|
此版本仍在开发中,尚未被视为稳定版。如需最新稳定版本,请使用 Spring Framework 7.0.6! |
JVM 检查点恢复
Spring Framework 与 Project CRaC 实现的检查点/恢复(checkpoint/restore)功能集成,从而支持构建能够减少基于 Spring 的 Java 应用程序在 JVM 上启动和预热时间的系统。
使用此功能需要:
-
支持检查点/恢复功能的 JVM(目前仅限 Linux)。
-
类路径中存在
org.crac:crac库(支持版本1.4.0及以上)。 -
指定所需的
java命令行参数,例如-XX:CRaCCheckpointTo=PATH或-XX:CRaCRestoreFrom=PATH。
当请求创建检查点时,在 -XX:CRaCCheckpointTo=PATH 指定的路径下生成的文件包含运行中 JVM 内存的表示形式,其中可能包含密钥及其他敏感数据。使用此功能时应假定 JVM “可见”的任何值(例如来自环境的配置属性)都会被存储在这些 CRaC 文件中。因此,必须仔细评估这些文件的生成位置、存储方式和访问权限所带来的安全影响。 |
从概念上讲,检查点和恢复与单个 Bean 的 Spring Lifecycle 契约 保持一致。
运行中应用程序的按需检查点/恢复
可以按需创建检查点(checkpoint),例如使用类似 jcmd application.jar JDK.checkpoint 的命令。在创建检查点之前,Spring 会停止所有正在运行的 Bean,如果这些 Bean 实现了 Lifecycle.stop 方法,则有机会关闭其持有的资源。在恢复(restore)之后,相同的 Bean 会被重新启动,通过 Lifecycle.start 方法,Bean 可以在需要时重新打开资源。对于不依赖 Spring 的库,可以通过实现 org.crac.Resource 并注册相应的实例,来提供自定义的检查点/恢复集成。
| 利用正在运行的应用程序的检查点/恢复功能,通常需要额外的生命周期管理,以优雅地停止和启动对文件或套接字等资源的使用,并停止活跃的线程。 |
请注意,当使用固定频率定义调度任务时(例如使用注解 @Scheduled(fixedRate = 5000)),在检查点(checkpoint)与恢复(restore)之间错过的所有执行,都将在 JVM 通过按需检查点/恢复机制恢复后立即执行。如果这不是您期望的行为,建议改用固定延迟(例如使用 @Scheduled(fixedDelay = 5000))或 cron 表达式来调度任务,因为这些方式的下一次执行时间是在每次任务执行完成后重新计算的。 |
| 如果检查点是在一个已预热的 JVM 上创建的,那么恢复后的 JVM 也将同样处于预热状态,从而可能立即达到峰值性能。此方法通常需要访问远程服务,因此需要一定程度的平台集成。 |
启动时自动检查点/恢复
当设置了 -Dspring.context.checkpoint=onRefresh JVM 系统属性时,会在启动过程中 LifecycleProcessor.onRefresh 阶段自动创建一个检查点。在此阶段完成后,所有非延迟初始化的单例对象都已被实例化,并且已调用 InitializingBean#afterPropertiesSet 回调方法;但此时生命周期尚未开始,ContextRefreshedEvent 事件也尚未发布。
出于测试目的,也可以利用 -Dspring.context.exit=onRefresh JVM 系统属性,它会触发类似的行为,但不会创建检查点,而是在相同的生命周期阶段直接退出 Spring 应用程序,且无需 Project CraC 依赖/JVM 或 Linux 环境。这有助于检查在 Bean 尚未启动时是否需要连接远程服务,并可能据此优化配置以避免此类依赖。
| 如上所述,尤其是在 CRaC 文件作为可部署工件(例如容器镜像)的一部分进行分发的使用场景中,请假定 JVM “看到”的任何敏感数据最终都会进入 CRaC 文件,并仔细评估相关的安全影响。 |
| 自动检查点/恢复(Automatic checkpoint/restore)是一种将应用程序启动“快进”到即将开始应用上下文阶段的方式,但它无法实现完全预热的 JVM。 |