|
此版本仍在开发中,尚未稳定。如需最新的稳定版本,请使用 Spring Framework 7.0.6! |
JVM 检查点与恢复
Spring 框架集成了由 Project CRaC 实现的检查点/恢复功能,以便实现能够减少基于 JVM 的 Spring Java 应用程序启动和预热时间的系统。
使用此功能需要:
-
支持检查点/恢复的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 并注册相关实例来提供自定义的检查点/恢复集成。
| 利用正在运行的应用程序的检查点/恢复功能通常需要额外的生命周期管理,以优雅地停止和开始使用文件或套接字等资源,并停止活动线程。 |
请注意,当以固定速率定义调度任务时(例如使用类似 @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阶段的方法。 |