本文为官方文档直译版本。原文链接
部署 Spring Boot 应用中文文档
- 引言
- 部署到云
-
- [Cloud Foundry](#Cloud Foundry)
- Kubernetes
-
- [Kubernetes 容器生命周期](#Kubernetes 容器生命周期)
- Heroku
- OpenShift
- 亚马逊网络服务(AWS)
-
- [AWS Elastic Beanstalk](#AWS Elastic Beanstalk)
-
- [使用 Tomcat 平台](#使用 Tomcat 平台)
- [使用 Java SE 平台](#使用 Java SE 平台)
- 总结
- [CloudCaptain 和亚马逊网络服务](#CloudCaptain 和亚马逊网络服务)
- Azure
- 谷歌云
- [安装 Spring Boot 应用程序](#安装 Spring Boot 应用程序)
-
- [作为 systemd 服务安装](#作为 systemd 服务安装)
- [作为 init.d 服务安装(System V)](#作为 init.d 服务安装(System V))
-
- [init.d 服务安全](#init.d 服务安全)
- 自定义启动脚本
-
- 自定义已编写的启动脚本
- 自定义运行时的脚本
-
- [使用 Conf Gile](#使用 Conf Gile)
- [Microsoft Windows 服务](#Microsoft Windows 服务)
- 高效部署
-
- [解压可执行 JAR](#解压可执行 JAR)
- [使用 JVM 提前处理](#使用 JVM 提前处理)
- [使用 JVM 检查点和还原](#使用 JVM 检查点和还原)
引言
Spring Boot 灵活的打包选项为部署应用程序提供了大量选择。您可以将 Spring Boot 应用程序部署到各种云平台、虚拟机/实机,或使其完全可在 Unix 系统上执行。
本节将介绍一些更常见的部署场景。
部署到云
Spring Boot 的可执行 jar 是现成的,适用于大多数流行的云 PaaS(Platform-as-a-Service,平台即服务)提供商。这些提供商往往要求您 "自带容器"。它们管理应用程序进程(而不是专门的 Java 应用程序),因此需要一个中间层来使您的应用程序适应云计算的运行进程概念。
Heroku 和 Cloud Foundry 这两个流行的云提供商采用了 "buildpack(构建包)" 方法。构建包将您部署的代码包装成启动应用程序所需的任何东西。它可能是 JDK 和 Java
调用、嵌入式 Web 服务器或完整的应用服务器。构建包是可插拔的,但在理想情况下,你应该尽可能少地对其进行定制。这样可以减少不在你控制范围内的功能。它能最大限度地减少开发环境和生产环境之间的差异。
理想情况下,您的应用程序就像一个 Spring Boot 可执行 jar,里面打包了运行所需的一切。
在本节中,我们将介绍如何在云中运行我们在 "入门" 部分开发的应用程序。
Cloud Foundry
Cloud Foundry 提供默认构建包,如果未指定其他构建包,这些构建包将发挥作用。Cloud Foundry Java 构建包非常支持 Spring 应用程序,包括 Spring Boot。您可以部署独立的可执行 jar 应用程序以及传统的 .war
打包应用程序。
一旦您构建了应用程序(例如使用 mvn clean package
)并安装了 cf 命令行工具,请使用 cf push
命令部署您的应用程序,并替换已编译 .jar
的路径。在推送应用程序之前,请确保已登录 cf 命令行客户端。下面一行显示了使用 cf push
命令部署应用程序的过程:
shell
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
在前面的示例中,我们将
acloudyspringtime
替换为cf
作为应用程序名称的任何值。
有关更多选项,请参阅 cf push 文档。如果同一目录中存在 Cloud Foundry manifest.yml 文件,则会考虑该文件。
此时,cf
将开始上传您的应用程序,并产生与以下示例类似的输出:
Uploading acloudyspringtime... OK
Preparing to start acloudyspringtime... OK
-----> Downloaded app package (8.9M)
-----> Java Buildpack Version: v3.12 (offline) | https://github.com/cloudfoundry/java-buildpack.git#6f25b7e
-----> Downloading Open Jdk JRE
Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.6s)
-----> Downloading Open JDK Like Memory Calculator 2.0.2_RELEASE from https://java-buildpack.cloudfoundry.org/memory-calculator/trusty/x86_64/memory-calculator-2.0.2_RELEASE.tar.gz (found in cache)
Memory Settings: -Xss349K -Xmx681574K -XX:MaxMetaspaceSize=104857K -Xms681574K -XX:MetaspaceSize=104857K
-----> Downloading Container Certificate Trust Store 1.0.0_RELEASE from https://java-buildpack.cloudfoundry.org/container-certificate-trust-store/container-certificate-trust-store-1.0.0_RELEASE.jar (found in cache)
Adding certificates to .java-buildpack/container_certificate_trust_store/truststore.jks (0.6s)
-----> Downloading Spring Auto Reconfiguration 1.10.0_RELEASE from https://java-buildpack.cloudfoundry.org/auto-reconfiguration/auto-reconfiguration-1.10.0_RELEASE.jar (found in cache)
Checking status of app 'acloudyspringtime'...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
1 of 1 instances running (1 running)
App started
恭喜您 应用程序已上线!
应用程序上线后,您可以使用 cf apps
命令验证已部署应用程序的状态,如下例所示:
shell
$ cf apps
Getting applications in ...
OK
name requested state instances memory disk urls
...
acloudyspringtime started 1/1 512M 1G acloudyspringtime.cfapps.io
...
一旦 Cloud Foundry 确认您的应用程序已部署,您就可以在给出的 URI 中找到该应用程序。在前面的示例中,您可以在 https://acloudyspringtime.cfapps.io/
找到它。
与服务绑定
默认情况下,有关运行应用程序的元数据以及服务连接信息将作为环境变量(例如:$VCAP_SERVICES
)暴露给应用程序。这一架构决定是由于 Cloud Foundry 的多语言性(可作为构建包支持任何语言和平台)。进程作用域环境变量与语言无关。
环境变量并不总是最简单的 API,因此 Spring Boot 会自动提取它们,并将数据扁平化为可通过 Spring 的Environment
抽象访问的属性,如下例所示:
java
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements EnvironmentAware {
private String instanceId;
@Override
public void setEnvironment(Environment environment) {
this.instanceId = environment.getProperty("vcap.application.instance_id");
}
// ...
}
所有 Cloud Foundry 属性均以 vcap
为前缀。您可以使用 vcap
属性访问应用程序信息(如应用程序的公共 URL)和服务信息(如数据库凭据)。有关完整的详细信息,请参阅 CloudFoundryVcapEnvironmentPostProcessor Javadoc。
Java CFEnv 项目更适合配置数据源等任务。
Kubernetes
Spring Boot 通过检查环境中的 "*_SERVICE_HOST
"和 "*_SERVICE_PORT
" 变量自动检测 Kubernetes 部署环境。您可以使用 spring.main.cloud-platform
配置属性覆盖此检测。
Spring Boot 可以帮助你管理应用程序的状态,并使用 Actuator 通过 HTTP Kubernetes Probes 输出。
Kubernetes 容器生命周期
当 Kubernetes 删除应用程序实例时,关机过程会同时涉及多个子系统:关机钩子、取消服务注册、从负载平衡器中移除实例...由于关机处理是并行发生的(而且由于分布式系统的特性),因此存在一个窗口,在此期间,流量可能会被路由到也已开始关机处理的 pod。
您可以在 preStop 处理程序中配置休眠执行,以避免请求被路由到已开始关闭的 pod。睡眠时间应足够长,以便新请求不再被路由到 pod,其持续时间因部署而异。可以使用 pod 配置文件中的 PodSpec 对预停止处理程序进行如下配置:
yaml
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
一旦预停止钩子完成,SIGTERM 就会发送到容器,然后开始优雅关机,允许完成任何剩余的处理中请求。
当 Kubernetes 向 pod 发送 SIGTERM 信号时,它会等待一段指定的时间,称为终止宽限期(默认为 30 秒)。如果容器在宽限期后仍在运行,它们就会被发送 SIGKILL 信号并被强制移除。如果 Pod 的关闭时间超过 30 秒,可能是因为增加了
spring.lifecycle.timeout-per-shutdown-phase
的时间,请确保通过设置 Pod YAML 中的terminationGracePeriodSeconds
选项来增加终止宽限期。
Heroku
Heroku 是另一个流行的 PaaS 平台。要定制 Heroku 的构建,您需要提供一个 Procfile
,它提供了部署应用程序所需的命令。Heroku 会为 Java 应用程序分配一个端口,然后确保路由到外部 URI 的工作正常。
您必须将应用程序配置为监听正确的端口。下面的示例显示了 REST 应用程序的Procfile
:
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot 将 -D
参数作为 Spring Environment
实例可访问的属性。server.port
配置属性会反馈给嵌入式 Tomcat、Jetty 或 Undertow 实例,然后在启动时使用该端口。$PORT
环境变量由 Heroku PaaS 分配给我们。
这就是你所需要的一切。Heroku 部署最常见的工作流程是通过 git push
将代码推送到生产环境,如下例所示:
shell
$ git push heroku main
其结果如下:
Initializing repository, done.
Counting objects: 95, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (78/78), done.
Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, done.
Total 95 (delta 31), reused 0 (delta 0)
-----> Java app detected
-----> Installing OpenJDK... done
-----> Installing Maven... done
-----> Installing settings.xml... done
-----> Executing: mvn -B -DskipTests=true clean install
[INFO] Scanning for projects...
Downloading: https://repo.spring.io/...
Downloaded: https://repo.spring.io/... (818 B at 1.8 KB/sec)
....
Downloaded: https://s3pository.heroku.com/jvm/... (152 KB at 595.3 KB/sec)
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/target/...
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/pom.xml ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.358s
[INFO] Finished at: Fri Mar 07 07:28:25 UTC 2014
[INFO] Final Memory: 20M/493M
[INFO] ------------------------------------------------------------------------
-----> Discovering process types
Procfile declares types -> web
-----> Compressing... done, 70.4MB
-----> Launching... done, v6
https://agile-sierra-1405.herokuapp.com/ deployed to Heroku
To git@heroku.com:agile-sierra-1405.git
* [new branch] main -> main
现在,您的应用程序应该可以在 Heroku 上运行了。有关详细信息,请参阅将 Spring Boot 应用程序部署到 Heroku。
OpenShift
OpenShift 有许多资源介绍如何部署 Spring Boot 应用程序,包括:
亚马逊网络服务(AWS)
Amazon Web Services 提供多种方式来安装基于 Spring Boot 的应用程序,既可以安装为传统的 Web 应用程序 (war) ,也可以安装为带有嵌入式 Web 服务器的可执行 jar 文件。这些选项包括:
- AWS Elastic Beanstalk
- AWS Code Deploy
- AWS OPS Works
- AWS Cloud Formation
- AWS Container Registry
每种方法都有不同的功能和定价模式。在本文中,我们将介绍使用 AWS Elastic Beanstalk 的方法。
AWS Elastic Beanstalk
正如 Elastic Beanstalk Java 官方指南所述,部署 Java 应用程序有两个主要选项。你可以使用 "Tomcat 平台" 或 "Java SE 平台"。
使用 Tomcat 平台
该选项适用于生成 war 文件的 Spring Boot 项目。无需特殊配置。只需遵循官方指南即可。
使用 Java SE 平台
该选项适用于生成 jar 文件并运行嵌入式 Web 容器的 Spring Boot 项目。Elastic Beanstalk 环境会在端口 80 上运行一个 nginx 实例,以代理在端口 5000 上运行的实际应用程序。要对其进行配置,请在 application.properties
文件中添加以下一行:
properties
server.port=5000
上传二进制文件而不是源代码
默认情况下,Elastic Beanstalk 会上传源代码并在 AWS 中编译。不过,最好还是上传二进制文件。为此,请在
.elasticbeanstalk/config.yml
文件中添加类似以下内容的行:
yaml
deploy:
artifact: target/demo-0.0.1-SNAPSHOT.jar
通过设置环境类型降低成本
默认情况下,Elastic Beanstalk 环境是负载平衡的。负载平衡器的成本很高。要避免这一成本,可将环境类型设置为 "单实例",如亚马逊文档中所述。你也可以使用 CLI 和以下命令创建单实例环境:
shell
eb create -s
总结
这是访问AWS最简单的方法之一,但还有更多内容需要涉及,例如如何将Elastic Beanstalk集成到任何CI/CD工具中,使用Elastic Beanstalk Maven插件而不是CLI等。有一篇博文详细介绍了这些主题。
CloudCaptain 和亚马逊网络服务
CloudCaptain 的工作原理是将您的 Spring Boot 可执行 jar 或 war 转换成最小的虚拟机映像,该映像可在 VirtualBox 或 AWS 上部署,且不会发生变化。CloudCaptain 与 Spring Boot 深度集成,并使用 Spring Boot 配置文件中的信息自动配置端口和健康检查 URL。CloudCaptain 将这些信息用于生成镜像以及提供所有资源(实例、安全组、弹性负载平衡器等)。
创建 CloudCaptain 帐户、将其连接到 AWS 帐户、安装最新版本的 CloudCaptain Client 并确保应用程序已由 Maven 或 Gradle 构建(例如使用 mvn clean package
)后,您就可以使用类似以下命令将 Spring Boot 应用程序部署到 AWS:
shell
$ boxfuse run myapp-1.0.jar -env=prod
默认情况下,CloudCaptain 会在启动时激活名为 boxfuse
的 Spring 配置文件。如果您的可执行 jar 或 war 中包含 application-boxfuse.properties 文件,CloudCaptain 将根据其中包含的属性进行配置。
此时,CloudCaptain 会为您的应用程序创建一个映像,上传该映像并在 AWS 上配置和启动必要的资源,从而产生与下例类似的输出:
Fusing Image for myapp-1.0.jar ...
Image fused in 00:06.838s (53937 K) -> axelfontaine/myapp:1.0
Creating axelfontaine/myapp ...
Pushing axelfontaine/myapp:1.0 ...
Verifying axelfontaine/myapp:1.0 ...
Creating Elastic IP ...
Mapping myapp-axelfontaine.boxfuse.io to 52.28.233.167 ...
Waiting for AWS to create an AMI for axelfontaine/myapp:1.0 in eu-central-1 (this may take up to 50 seconds) ...
AMI created in 00:23.557s -> ami-d23f38cf
Creating security group boxfuse-sg_axelfontaine/myapp:1.0 ...
Launching t2.micro instance of axelfontaine/myapp:1.0 (ami-d23f38cf) in eu-central-1 ...
Instance launched in 00:30.306s -> i-92ef9f53
Waiting for AWS to boot Instance i-92ef9f53 and Payload to start at https://52.28.235.61/ ...
Payload started in 00:29.266s -> https://52.28.235.61/
Remapping Elastic IP 52.28.233.167 to i-92ef9f53 ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Deployment completed successfully. axelfontaine/myapp:1.0 is up and running at https://myapp-axelfontaine.boxfuse.io/
您的应用程序现在应该可以在 AWS 上运行了。
请参阅在 EC2 上部署 Spring Boot 应用程序的博文以及 CloudCaptain Spring Boot 集成的文档,开始使用 Maven 构建运行应用程序。
Azure
本入门指南将指导您将 Spring Boot 应用程序部署到 Azure Spring Cloud 或 Azure App Service。
谷歌云
Google Cloud 有多个可用于启动 Spring Boot 应用程序的选项。最容易上手的可能是 App Engine,但您也可以通过 Container Engine 在容器中运行 Spring Boot,或通过 Compute Engine 在虚拟机上运行 Spring Boot。
要在 App Engine 标准环境中运行您的第一个应用程序,请参考本教程。
另外,App Engine Flex 还要求你创建一个 app.yaml
文件来描述应用程序所需的资源。通常,您可以将该文件放在 src/main/appengine
中,它应该与下面的文件类似:
yaml
service: "default"
runtime: "java17"
env: "flex"
handlers:
- url: "/.*"
script: "this field is required, but ignored"
manual_scaling:
instances: 1
health_check:
enable_health_check: false
env_variables:
ENCRYPT_KEY: "your_encryption_key_here"
您可以在构建配置中添加项目 ID 来部署应用程序(例如使用 Maven 插件),如下例所示:
xml
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.4.4</version>
<configuration>
<project>myproject</project>
</configuration>
</plugin>
然后使用 mvn appengine:deploy
进行部署(需要先进行身份验证,否则会导致构建失败)。
安装 Spring Boot 应用程序
除了直接使用 java -jar
运行 Spring Boot 应用程序外,还可以将其作为 systemd
、init.d
或 Windows 服务运行。
作为 systemd 服务安装
systemd
是 System V init 系统的后继者,目前已被许多现代 Linux 发行版所采用。Spring Boot 应用程序可通过 systemd
"服务" 脚本启动。
假设你在 /var/myapp
目录中将 Spring Boot 应用程序打包为 uber jar,要将其安装为 systemd
服务,需要创建名为 myapp.service
的脚本并将其放置在 /etc/systemd/system
目录中。下面的脚本提供了一个示例:
[Unit]
Description=myapp
After=syslog.target network.target
[Service]
User=myapp
Group=myapp
Environment="JAVA_HOME=/path/to/java/home"
ExecStart=${JAVA_HOME}/bin/java -jar /var/myapp/myapp.jar
ExecStop=/bin/kill -15 $MAINPID
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
请记住,要为您的应用程序更改
Description
、User
、Group
、Environment
和ExecStart
字段。
ExecStart
字段没有声明脚本操作命令,这意味着默认使用运行命令。
运行应用程序的用户、PID 文件和控制台日志文件由 systemd
本身管理,因此必须在 "服务" 脚本中使用相应字段进行配置。详情请查阅服务单元配置手册。
要标记应用程序在系统启动时自动启动,请使用以下命令:
shell
$ systemctl enable myapp.service
运行 man systemctl
了解更多详情。
作为 init.d 服务安装(System V)
要将应用程序作为 init.d
服务使用,请将其构建配置为生成完全可执行的 jar。
完全可执行的 jar 通过在文件前面嵌入一个额外的脚本来工作。目前,有些工具不接受这种格式,所以你可能并不总是能使用这种技术。例如,
jar -xf
可能无法解压缩完全可执行的 jar 或 war。建议您只有在打算直接执行 jar 或 war 时才将其设置为完全可执行,而不是使用java -jar
运行或将其部署到 servlet 容器中。
zip64 格式的 jar 文件无法完全执行。如果尝试这样做,在直接执行或使用java -jar
执行时,jar 文件将被报告为损坏。包含一个或多个 zip64 格式嵌套 jar 的标准格式 jar 文件可以完全执行。
要使用 Maven 创建 "完全可执行" 的 jar,请使用以下插件配置:
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
下面的示例显示了相应的 Gradle 配置:
groovy
tasks.named('bootJar') {
launchScript()
}
然后,可以将其链接到 init.d
,以支持标准的start
、stop
、restart
和status
命令。
添加到完全可执行 jar 中的默认启动脚本支持大多数 Linux 发行版,并已在 CentOS 和 Ubuntu 上进行了测试。其他平台,如 OS X 和 FreeBSD,需要使用自定义脚本。默认脚本支持以下功能:
- 以拥有 jar 文件的用户身份启动服务
- 使用
/var/run/<appname>/<appname>.pid
跟踪应用程序的 PID - 将控制台日志写入
/var/log/<appname>.log
假设在 /var/myapp
中安装了 Spring Boot 应用程序,要将 Spring Boot 应用程序安装为 init.d
服务,请创建一个符号链接,如下所示:
shell
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
安装完成后,您可以按照常规方法启动或停止服务。例如,在基于 Debian 的系统上,可以使用以下命令启动服务:
shell
$ service myapp start
如果应用程序无法启动,请检查写入
/var/log/<appname>.log
的日志文件是否有错误。
您也可以使用标准操作系统工具标记应用程序自动启动。例如,在 Debian 上,您可以使用以下命令:
shell
$ update-rc.d myapp defaults <priority>
init.d 服务安全
以下是一套关于如何确保作为
init.d
服务运行的 Spring Boot 应用程序安全的指南。它并不打算详尽无遗地列出加固应用程序及其运行环境应采取的所有措施。
以根用户身份执行时(如使用根用户启动 init.d 服务),默认可执行脚本会以 RUN_AS_USER
环境变量中指定的用户身份运行应用程序。如果未设置该环境变量,则会使用拥有 jar 文件的用户。您绝不能以 root 用户身份运行 Spring Boot 应用程序,因此 RUN_AS_USER
绝不应该是 root 用户,应用程序的 jar 文件也绝不应该由 root 用户拥有。相反,应创建一个特定用户来运行应用程序,并设置 RUN_AS_USER
环境变量或使用 chown
使其成为 jar 文件的所有者,如下例所示:
shell
$ chown bootapp:bootapp your-app.jar
为降低应用程序用户账户被入侵的几率,应考虑阻止其使用 shell 登录。例如,可以将账户的 shell 设置为
/usr/sbin/nologin
。
您还应采取措施防止应用程序的 jar 文件被修改。首先,配置其权限,使其不能被写入,只能由所有者读取或执行,如下例所示:
shell
$ chmod 500 your-app.jar
其次,如果您的应用程序或运行该程序的账户被入侵,您还应采取措施限制损失。如果攻击者确实获得了访问权限,他们可以使 jar 文件可写并更改其内容。防止这种情况的一种方法是使用 chattr
使其不可变,如下例所示:
shell
$ sudo chattr +i your-app.jar
这将防止包括 root 用户在内的任何用户修改 jar。
如果使用 root 用户控制应用程序的服务,并使用 .conf 文件自定义启动,则 .conf
文件将由 root 用户读取和评估。因此应确保该文件的安全。如以下示例所示,使用 chmod
使文件只能由所有者读取,并使用 chown
使根用户成为所有者:
shell
$ chmod 400 your-app.conf
$ sudo chown root:root your-app.conf
自定义启动脚本
由 Maven 或 Gradle 插件编写的默认嵌入式启动脚本可以通过多种方式进行自定义。对于大多数人来说,使用默认脚本并进行一些自定义通常就足够了。如果你发现自己无法自定义需要的内容,可以使用 embeddedLaunchScript
选项完全编写自己的文件。
自定义已编写的启动脚本
在将启动脚本写入 jar 文件时,自定义启动脚本的元素往往很有意义。例如,init.d 脚本可以提供 "description"。既然你事先知道描述(而且不需要更改),那么不妨在生成 jar 时提供它。
要自定义写入的元素,请使用 Spring Boot Maven 插件的 embeddedLaunchScriptProperties
选项或 Spring Boot Gradle 插件的 launchScript 的 properties 属性。
默认脚本支持以下属性替换:
属性名称 | 描述 | Gradle 默认值 | Maven 默认值 |
---|---|---|---|
mode |
脚本模式。 | auto |
auto |
initInfoProvides |
"INIT INFO"的 Provides 部分 |
${task.baseName} |
${project.artifactId} |
initInfoRequiredStart |
"INIT INFO"的 Required-Start 部分 |
$remote_fs $syslog $network |
$remote_fs $syslog $network |
initInfoRequiredStop |
"INIT INFO"的 Required-Stop 部分 |
$remote_fs $syslog $network |
$remote_fs $syslog $network |
initInfoDefaultStart |
"INIT INFO"的 Default-Start 部分 |
2 3 4 5 |
2 3 4 5 |
initInfoDefaultStop |
"INIT INFO"的 Default-Stop 部分 |
0 1 6 |
0 1 6 |
initInfoShortDescription |
"INIT INFO"的 Short-Description 部分 |
${project.description} 的单行版本(回退至 ${task.baseName} ) |
${project.name} |
initInfoDescription |
"INIT INFO"的 Short-Description 部分 |
${project.description} (回退至 ${task.baseName} ) |
${project.description} (回退至 ${project.name} ) |
initInfoChkconfig |
"INIT INFO"的 chkconfig 部分 |
2345 99 01 |
2345 99 01 |
confFolder |
默认值为CONF_FOLDER |
包含 jar 的文件夹 | 包含 jar 的文件夹 |
inlinedConfScript |
默认启动脚本中应内联的文件脚本引用。它可用于在加载任何外部配置文件前设置环境变量(如 JAVA_OPTS )。 |
||
logFolder |
LOG_FOLDER 的默认值。仅对 init.d 服务有效 |
||
logFilename |
LOG_FILENAME 的默认值。仅对 init.d 服务有效 |
||
pidFolder |
PID_FOLDER 的默认值。仅对 init.d 服务有效 |
||
pidFilename |
PID_FOLDER 中 PID 文件名的默认值。仅对 init.d 服务有效 |
||
useStartStopDaemon |
当start-stop-daemon 进程命令可用时,是否应使用该命令来控制进程 |
true |
true |
stopWaitTime |
STOP_WAIT_TIME 的默认值(秒)。仅对 init.d 服务有效 |
60 |
60 |
自定义运行时的脚本
对于写入 jar 后需要自定义的脚本项目,可以使用环境变量或配置文件。
默认脚本支持以下环境属性:
变量 | 描述 |
---|---|
MODE |
运行 "模式"。默认值取决于 jar 的构建方式,但通常是auto (这意味着它会通过检查它是否是 init.d 目录中的一个符号链接来猜测它是否是一个启动脚本)。你可以明确地将其设置为 service ,这样 stop|start|status|restart 命令就能正常工作;如果你想在前台运行脚本,也可以将其设置为 run 。 |
RUN_AS_USER |
用于运行应用程序的用户。未设置时,将使用拥有 jar 文件的用户。 |
USE_START_STOP_DAEMON |
当start-stop-daemon 进程命令可用时,是否应使用该命令来控制进程。默认为 true 。 |
PID_FOLDER |
pid 文件夹的根名称(默认为 /var/run )。 |
LOG_FOLDER |
存放日志文件的文件夹名称(默认为 /var/log )。 |
CONF_FOLDER |
读取 .conf 文件的文件夹名称(默认情况下与 jar-file 文件夹相同)。 |
LOG_FILENAME |
LOG_FOLDER 中日志文件的名称(默认为 <appname>.log )。 |
APP_NAME |
应用程序名称。如果 jar 是通过符号链接运行的,脚本会猜测应用程序的名称。如果它不是一个符号链接,或者你想明确设置应用程序名称,这可能会很有用。 |
RUN_ARGS |
传给程序(Spring Boot 应用程序)的参数。 |
JAVA_HOME |
java 可执行文件的位置默认通过 PATH 查找,但如果在 $JAVA_HOME/bin/java 处有可执行文件,则可以明确设置。 |
JAVA_OPTS |
启动 JVM 时传递给它的选项。 |
JARFILE |
jar 文件的明确位置,以防脚本被用于启动实际上未嵌入的 jar。 |
DEBUG |
如果不为空,则在 shell 进程中设置 -x 标志,以便查看脚本中的逻辑。 |
STOP_WAIT_TIME |
停止应用程序后强制关闭前的等待时间(默认为 60 秒)。 |
PID_FOLDER
、LOG_FOLDER
和LOG_FILENAME
变量仅对init.d
服务有效。对于systemd
,可使用 "service" 脚本进行相应的自定义设置。更多详情,请参阅服务单元配置手册。
使用 Conf Gile
除 JARFILE
和 APP_NAME
外,上一节中列出的设置均可通过 .conf
文件进行配置。该文件应位于 jar 文件旁边,名称相同,但后缀为 .conf
而不是 .jar
。例如,名为 /var/myapp/myapp.jar
的 jar 文件使用名为 /var/myapp/myapp.conf
的配置文件,如下例所示:
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
如果不喜欢将配置文件放在 jar 文件旁边,可以设置
CONF_FOLDER
环境变量,自定义配置文件的位置。
要了解如何适当保护该文件,请参阅保护 init.d 服务的指南。
Microsoft Windows 服务
可以使用 winsw 将 Spring Boot 应用程序作为 Windows 服务启动。
本文档(单独维护的示例)将逐步介绍如何为 Spring Boot 应用程序创建 Windows 服务。
高效部署
解压可执行 JAR
如果从容器中运行应用程序,可以使用可执行 jar,但将其解压缩并以另一种方式运行通常也有好处。某些 PaaS 实现也可能选择在运行前解压缩存档。例如,Cloud Foundry 就是这样运行的。运行解压缩存档的一种方法是启动相应的启动器,如下所示:
shell
$ jar -xf myapp.jar
$ java org.springframework.boot.loader.launch.JarLauncher
实际上,启动时的速度(取决于 jar 的大小)要比从未爆发的压缩包运行时稍快一些。启动后,就不会有任何差别了。
解压缩 jar 文件后,还可以通过使用 "自然" 主方法而不是 JarLauncher
运行应用程序来额外延长启动时间。例如:
shell
$ jar -xf myapp.jar
$ java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.example.MyApplication
在应用程序的主方法上使用
JarLauncher
还有一个好处,那就是类路径顺序可以预测。jar 中包含一个classpath.idx
文件,JarLauncher
在构建类路径时会使用该文件。
使用 JVM 提前处理
使用 AOT 生成的初始化代码运行应用程序对启动时间非常有利。首先,您需要确保构建的 jar 包含 AOT 生成的代码。
对于 Maven 而言,这意味着您在构建时应使用 -Pnative
激活native
配置文件:
shell
$ mvn -Pnative package
对于 Gradle,您需要确保您的构建包含 org.springframework.boot.aot
插件。
JAR 生成后,运行时将 spring.aot.enabled
系统属性设置为 true
。例如
shell
$ java -Dspring.aot.enabled=true -jar myapplication.jar
........ Starting AOT-processed MyApplication ...
要注意的是,使用超前处理有其缺点。它意味着以下限制:
- 类路径是固定的,在构建时已完全定义
- 应用程序中定义的Bean类在运行时不会改变,这意味着
- Spring
@Profile
注解和特定于配置文件的配置有其局限性。 - 不支持在创建 Bean 时改变的属性(例如,
@ConditionalOnProperty
和.enable
属性)。
- Spring
要了解有关超前处理的更多信息,请参阅了解Spring超前处理部分。
使用 JVM 检查点和还原
Coordinated Restore at Checkpoint(CRaC)是一个 OpenJDK 项目,它定义了一个新的 Java API,允许您在 HotSpot JVM 上检查点和还原应用程序。它基于在 Linux 上实现检查点/还原功能的 CRIU 项目。
其原理如下:几乎像往常一样启动应用程序,但使用的是支持 CRaC 的 JDK 版本,如支持 CRaC 的 Bellsoft Liberica JDK 或支持 CRaC 的 Azul Zulu JDK。然后在某个时间点,可能是在通过执行所有常用代码路径热身 JVM 的某些工作负载之后,使用 API 调用、jcmd
命令、HTTP 端点或其他机制触发检查点。
然后,运行中的 JVM 的内存表示(包括其预热)会被序列化到磁盘上,这样就可以在稍后的时间点快速还原,可能是在另一台具有类似操作系统和 CPU 架构的机器上。恢复后的进程保留了 HotSpot JVM 的所有功能,包括运行时的进一步 JIT 优化。
基于 Spring Framework 提供的基础,Spring Boot 支持检查点和恢复应用程序,并在有限的范围内管理资源(如套接字、文件和线程池)的开箱即用生命周期。预计其他依赖项和处理此类资源的应用程序代码还需要额外的生命周期管理。
有关支持的两种模式("按需检查点/还原运行中的应用程序 "和 "启动时自动检查点/还原")、如何启用检查点和还原支持以及一些指南的更多详情,请参阅 Spring Framework JVM 检查点还原支持文档。