此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.3! |
部署到云
Spring Boot 的可执行 jar 对于大多数流行的云 PaaS(平台即服务)提供商来说是现成的。 这些提供商往往要求您 “自带容器”。 它们管理应用程序进程(而不是专门管理 Java 应用程序),因此它们需要一个中间层,使您的应用程序适应云中正在运行的进程的概念。
两个流行的云提供商 Heroku 和 Cloud Foundry 采用“buildpack”方法。
buildpack 将您部署的代码包装在启动应用程序所需的任何内容中。
它可能是一个 JDK 和对java
、嵌入式 Web 服务器或成熟的应用程序服务器。
buildpack 是可插拔的,但理想情况下,您应该能够通过尽可能少的自定义来获得它。
这减少了不受您控制的功能的占用空间。
它最大限度地减少了开发和生产环境之间的差异。
理想情况下,你的应用程序(如 Spring Boot 可执行 jar)具有打包运行所需的一切。
在本节中,我们将了解如何在云中启动并运行我们在 “入门” 部分中开发的应用程序。
云铸造
Cloud Foundry 提供了默认的 buildpack,如果未指定其他 buildpack,则这些 buildpack 将发挥作用。
Cloud Foundry Java buildpack 对 Spring 应用程序(包括 Spring Boot)提供了出色的支持。
您可以部署独立的可执行 jar 应用程序以及传统的.war
打包的应用程序。
构建应用程序(例如,通过使用mvn clean package
) 并具有安装了cf
命令行工具,请使用cf push
命令,将路径替换为已编译的.jar
.
请务必拥有使用您的cf
命令行客户端在推送应用程序之前。
以下行显示了使用cf push
命令部署应用程序:
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
在前面的示例中,我们将acloudyspringtime 无论您提供什么价值cf 作为应用程序的名称。 |
请参阅cf push
文档以获取更多选项。
如果有 Cloud Foundrymanifest.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
命令,如以下示例所示:
$ 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 的多语言(任何语言和平台都可以作为 buildpack 支持)的性质。
进程范围的环境变量与语言无关。
环境变量并不总是最简单的 API,因此 Spring Boot 会自动提取它们并将数据扁平化为可以通过 Spring 的Environment
abstraction 的 Abstraction 进行抽象作,如以下示例所示:
-
Java
-
Kotlin
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");
}
// ...
}
import org.springframework.context.EnvironmentAware
import org.springframework.core.env.Environment
import org.springframework.stereotype.Component
@Component
class MyBean : EnvironmentAware {
private var instanceId: String? = null
override fun setEnvironment(environment: Environment) {
instanceId = environment.getProperty("vcap.application.instance_id")
}
// ...
}
All Cloud Foundry properties are prefixed with vcap
.
You can use vcap
properties to access application information (such as the public URL of the application) and service information (such as database credentials).
See the CloudFoundryVcapEnvironmentPostProcessor
API documentation for complete details.
The Java CFEnv project is a better fit for tasks such as configuring a DataSource.
Kubernetes
Spring Boot auto-detects Kubernetes deployment environments by checking the environment for "*_SERVICE_HOST"
and "*_SERVICE_PORT"
variables.
You can override this detection with the spring.main.cloud-platform
configuration property.
Spring Boot helps you to manage the state of your application and export it with HTTP Kubernetes Probes using Actuator.
Kubernetes Container Lifecycle
When Kubernetes deletes an application instance, the shutdown process involves several subsystems concurrently: shutdown hooks, unregistering the service, removing the instance from the load-balancer…
Because this shutdown processing happens in parallel (and due to the nature of distributed systems), there is a window during which traffic can be routed to a pod that has also begun its shutdown processing.
You can configure a sleep execution in a preStop handler to avoid requests being routed to a pod that has already begun shutting down.
This sleep should be long enough for new requests to stop being routed to the pod and its duration will vary from deployment to deployment.
If you’re using Kubernetes 1.32 or up, the preStop handler can be configured by using the PodSpec in the pod’s configuration file as follows:
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
sleep:
seconds: 10
If you’re not on Kubernetes 1.32 yet, you can use an exec
command to invoke sleep
.
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
The container needs to have a shell for this to work.
Once the pre-stop hook has completed, SIGTERM will be sent to the container and graceful shutdown will begin, allowing any remaining in-flight requests to complete.
When Kubernetes sends a SIGTERM signal to the pod, it waits for a specified time called the termination grace period (the default for which is 30 seconds).
If the containers are still running after the grace period, they are sent the SIGKILL signal and forcibly removed.
If the pod takes longer than 30 seconds to shut down, which could be because you have increased spring.lifecycle.timeout-per-shutdown-phase
, make sure to increase the termination grace period by setting the terminationGracePeriodSeconds
option in the Pod YAML.
Heroku
Heroku is another popular PaaS platform.
To customize Heroku builds, you provide a Procfile
, which provides the incantation required to deploy an application.
Heroku assigns a port
for the Java application to use and then ensures that routing to the external URI works.
You must configure your application to listen on the correct port.
The following example shows the Procfile
for our starter REST application:
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot makes -D
arguments available as properties accessible from a Spring Environment
instance.
The server.port
configuration property is fed to the embedded Tomcat, Jetty, or Undertow instance, which then uses the port when it starts up.
The $PORT
environment variable is assigned to us by the Heroku PaaS.
This should be everything you need.
The most common deployment workflow for Heroku deployments is to git push
the code to production, as shown in the following example:
$ git push heroku main
Which will result in the following:
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 [email protected]:agile-sierra-1405.git
* [new branch] main -> main
Your application should now be up and running on Heroku.
For more details, see Deploying Spring Boot Applications to Heroku.
OpenShift
OpenShift has many resources describing how to deploy Spring Boot applications, including:
Amazon Web Services (AWS)
Amazon Web Services offers multiple ways to install Spring Boot-based applications, either as traditional web applications (war) or as executable jar files with an embedded web server.
The options include:
-
AWS Elastic Beanstalk
-
AWS Code Deploy
-
AWS OPS Works
-
AWS Cloud Formation
-
AWS Container Registry
Each has different features and pricing models.
In this document, we describe to approach using AWS Elastic Beanstalk.
AWS Elastic Beanstalk
As described in the official Elastic Beanstalk Java guide, there are two main options to deploy a Java application.
You can either use the “Tomcat Platform” or the “Java SE platform”.
Using the Tomcat Platform
This option applies to Spring Boot projects that produce a war file.
No special configuration is required.
You need only follow the official guide.
Using the Java SE Platform
This option applies to Spring Boot projects that produce a jar file and run an embedded web container.
Elastic Beanstalk environments run an nginx instance on port 80 to proxy the actual application, running on port 5000.
To configure it, add the following line to your application.properties
file:
-
Properties
-
YAML
server.port=5000
server:
port: 5000
Upload binaries instead of sources
By default, Elastic Beanstalk uploads sources and compiles them in AWS.
However, it is best to upload the binaries instead.
To do so, add lines similar to the following to your .elasticbeanstalk/config.yml
file:
deploy:
artifact: target/demo-0.0.1-SNAPSHOT.jar
Reduce costs by setting the environment type
By default an Elastic Beanstalk environment is load balanced.
The load balancer has a significant cost.
To avoid that cost, set the environment type to “Single instance”, as described in the Amazon documentation.
You can also create single instance environments by using the CLI and the following command:
eb create -s
Summary
This is one of the easiest ways to get to AWS, but there are more things to cover, such as how to integrate Elastic Beanstalk into any CI / CD tool, use the Elastic Beanstalk Maven plugin instead of the CLI, and others.
There is a blog post covering these topics more in detail.
CloudCaptain and Amazon Web Services
CloudCaptain works by turning your Spring Boot executable jar or war into a minimal VM image that can be deployed unchanged either on VirtualBox or on AWS.
CloudCaptain comes with deep integration for Spring Boot and uses the information from your Spring Boot configuration file to automatically configure ports and health check URLs.
CloudCaptain leverages this information both for the images it produces as well as for all the resources it provisions (instances, security groups, elastic load balancers, and so on).
Once you have created a CloudCaptain account, connected it to your AWS account, installed the latest version of the CloudCaptain Client, and ensured that the application has been built by Maven or Gradle (by using, for example, mvn clean package
), you can deploy your Spring Boot application to AWS with a command similar to the following:
$ boxfuse run myapp-1.0.jar -env=prod
See the boxfuse run
documentation for more options.
If there is a boxfuse.conf
file present in the current directory, it is considered.
By default, CloudCaptain activates a Spring profile named boxfuse
on startup.
If your executable jar or war contains an application-boxfuse.properties
file, CloudCaptain bases its configuration on the properties it contains.
At this point, CloudCaptain creates an image for your application, uploads it, and configures and starts the necessary resources on AWS, resulting in output similar to the following example:
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/
Your application should now be up and running on AWS.
See the blog post on deploying Spring Boot apps on EC2 as well as the documentation for the CloudCaptain Spring Boot integration to get started with a Maven build to run the app.
Azure
This Getting Started guide walks you through deploying your Spring Boot application to either Azure Spring Cloud or Azure App Service.
Google Cloud
Google Cloud has several options that can be used to launch Spring Boot applications.
The easiest to get started with is probably App Engine, but you could also find ways to run Spring Boot in a container with Container Engine or on a virtual machine with Compute Engine.
To deploy your first app to App Engine standard environment, follow this tutorial.
Alternatively, App Engine Flex requires you to create an app.yaml
file to describe the resources your app requires.
Normally, you put this file in src/main/appengine
, and it should resemble the following file:
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"
You can deploy the app (for example, with a Maven plugin) by adding the project ID to the build configuration, as shown in the following example:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.4.4</version>
<configuration>
<project>myproject</project>
</configuration>
</plugin>
Then deploy with mvn appengine:deploy
(you need to authenticate first, otherwise the build fails).