Efficient deployments

Unpacking the Executable JAR

如果你的应用程序在容器中运行,你可以使用可执行 jar,但将其解包并以不同的方式运行,通常也更有利。某些 PaaS 实现也可能会在运行前解包归档文件。比如,Cloud Foundry 就是这样操作的。按以下方式启动相应的启动器,是运行解包归档文件的一种方法:

If you are running your application from a container, you can use an executable jar, but it is also often an advantage to explode it and run it in a different way. Certain PaaS implementations may also choose to unpack archives before they run. For example, Cloud Foundry operates this way. One way to run an unpacked archive is by starting the appropriate launcher, as follows:

$ jar -xf myapp.jar
$ java org.springframework.boot.loader.launch.JarLauncher

实际上,这种方式的启动速度会稍微快一些(根据 jar 的大小),而不是从未解包的归档文件启动。启动之后,你就不应再期望有任何差异。

This is actually slightly faster on startup (depending on the size of the jar) than running from an unexploded archive. After startup, you should not expect any differences.

在解压 JAR 文件后,还可以通过使用该应用程序的“自然”main 方法,而不是 `JarLauncher`来运行该应用程序,从而获得额外的启动时间加速。例如:

Once you have unpacked the jar file, you can also get an extra boost to startup time by running the app with its "natural" main method instead of the JarLauncher. For example:

$ jar -xf myapp.jar
$ java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.example.MyApplication

在应用程序的 main 方法上使用 `JarLauncher`可以额外获得可预测的类路径顺序。该 jar 包含一个 `classpath.idx`文件,`JarLauncher`在构建类路径时会使用该文件。

Using the JarLauncher over the application’s main method has the added benefit of a predictable classpath order. The jar contains a classpath.idx file which is used by the JarLauncher when constructing the classpath.

Using Ahead-of-time Processing With the JVM

使用 AOT 生成的初始化代码来运行应用程序,对启动时间非常有帮助。首先,你需要确保你编译的 jar 包中包括 AOT 生成的代码。

It’s beneficial for the startup time to run your application using the AOT generated initialization code. First, you need to ensure that the jar you are building includes AOT generated code.

对于 Maven,这意味着你应该使用 `-Pnative`编译以激活 `native`配置文件:

For Maven, this means that you should build with -Pnative to activate the native profile:

$ mvn -Pnative package

对于 Gradle,你需要确保编译中包括 `org.springframework.boot.aot`插件。

For Gradle, you need to ensure that your build includes the org.springframework.boot.aot plugin.

当编译完成后,使用设置了 `true`的 `spring.aot.enabled`系统属性运行该应用程序。例如:

When the JAR has been built, run it with spring.aot.enabled system property set to true. For example:

$ java -Dspring.aot.enabled=true -jar myapplication.jar

........ Starting AOT-processed MyApplication ...

请注意,使用提前处理存在缺点。这意味着以下限制:

Beware that using the ahead-of-time processing has drawbacks. It implies the following restrictions:

  • The classpath is fixed and fully defined at build time

  • The beans defined in your application cannot change at runtime, meaning:

    • The Spring @Profile annotation and profile-specific configuration have limitations.

    • Properties that change if a bean is created are not supported (for example, @ConditionalOnProperty and .enable properties).

如需了解有关提前处理的更多信息,请参阅 Understanding Spring Ahead-of-Time Processing section

To learn more about ahead-of-time processing, please see the Understanding Spring Ahead-of-Time Processing section.

Checkpoint and Restore With the JVM

Coordinated Restore at Checkpoint (CRaC) 是一个 OpenJDK 项目,它定义了一个新的 Java API,使你能够在 HotSpot JVM 上检查点和恢复应用程序。它基于 CRIU,一个在 Linux 上实现检查点/恢复功能的项目。

Coordinated Restore at Checkpoint (CRaC) is an OpenJDK project that defines a new Java API to allow you to checkpoint and restore an application on the HotSpot JVM. It is based on CRIU, a project that implements checkpoint/restore functionality on Linux.

原则是:你按通常的方式启动应用程序,但需使用 CRac 启用的 JDK 版本,比如 BellSoft Liberica JDK with CRaCAzul Zulu JDK with CRaC。然后在某个时间点,可能在通过执行所有通用代码路径预热 JVM 的一些工作负载之后,你可以使用 API 调用(`jcmd`命令、HTTP 端点或其他机制)触发一个检查点。

The principle is the following: you start your application almost as usual but with a CRaC enabled version of the JDK like BellSoft Liberica JDK with CRaC or Azul Zulu JDK with CRaC. Then at some point, potentially after some workloads that will warm up your JVM by executing all common code paths, you trigger a checkpoint using an API call, a jcmd command, an HTTP endpoint, or a different mechanism.

然后,正在运行的 JVM 的内存表示(包括其热度)序列化到磁盘中,这允许在稍后的时间点进行快速恢复,甚至可以在具有类似操作系统和 CPU 架构的另一台计算机上进行恢复。已恢复的进程保留了 HotSpot JVM 的所有功能,包括在运行时进行进一步 JIT 优化。

A memory representation of the running JVM, including its warmness, is then serialized to disk, allowing a fast restoration at a later point, potentially on another machine with a similar operating system and CPU architecture. The restored process retains all the capabilities of the HotSpot JVM, including further JIT optimizations at runtime.

Spring Boot 在 Spring Framework 提供的基础上,为检查点和恢复应用程序提供支持,并开箱即用地管理资源的生命周期,例如套接字、文件和线程池 on a limited scope。针对其他依赖项以及可能处理此类资源的应用程序代码,预计会进行额外的生命周期管理。

Based on the foundations provided by Spring Framework, Spring Boot provides support for checkpointing and restoring your application, and manages out-of-the-box the lifecycle of resources such as socket, files and thread pools on a limited scope. Additional lifecycle management is expected for other dependencies and potentially for the application code dealing with such resources.

你可以在 {url-spring-framework-docs}/integration/checkpoint-restore.html[Spring Framework JVM 检查点恢复支持文档] 中找到有关支持的两种模式(“正在运行应用程序的按需检查点/恢复”和“启动时的自动检查点/恢复”)的更多详细信息,以及如何启用检查点和恢复支持以及一些指南。

You can find more details about the two modes supported ("on demand checkpoint/restore of a running application" and "automatic checkpoint/restore at startup"), how to enable checkpoint and restore support and some guidelines in {url-spring-framework-docs}/integration/checkpoint-restore.html[the Spring Framework JVM Checkpoint Restore support documentation].