跳到主要内容

JVM 检查点恢复

ChatGPT-4o-mini 中英对照 JVM Checkpoint Restore

Spring 框架与 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 生命周期契约 对齐。

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

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

注意

利用正在运行的应用程序的检查点/恢复通常需要额外的生命周期管理,以优雅地停止和启动使用文件或套接字等资源,并停止活动线程。

注意

请注意,当以固定速率定义调度任务时,例如使用注解 @Scheduled(fixedRate = 5000),在检查点和恢复之间所有错过的执行将在 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 文件中,并仔细评估相关的安全影响。

备注

自动检查点/恢复是一种将应用程序启动“快进”到即将开始应用程序上下文的阶段的方法,但它不允许拥有一个完全预热的 JVM。