JVM 检查点恢复

Spring Framework 与 Project CRaC 实现的检查点/恢复集成,旨在允许实现能够减少基于 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 合同保持一致。

运行中应用程序的按需检查点/恢复

可以根据需要创建检查点,例如使用类似 jcmd application.jar JDK.checkpoint 的命令。在创建检查点之前,Spring 停止所有运行中的 bean,让它们有机会关闭资源(如果需要通过实现 Lifecycle.stop)。恢复后,相同的 bean 将重新启动,使用 Lifecycle.start 允许 bean 在相关时重新打开资源。对于不依赖于 Spring 的库,可以通过实现 org.crac.Resource 并注册相关实例来提供自定义检查点/恢复集成。

利用运行中应用程序的检查点/恢复通常需要额外的生命周期管理,以优雅地停止和启动使用文件或套接字的资源,并停止活动线程。
如果在已经热身的 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 文件中,并仔细评估相关的安全性影响。
自动检查点/恢复是一种将应用程序启动快进到即将启动应用程序上下文的阶段的方法,但不允许拥有完全热身的 JVM。