部署到云端

Spring Boot 的可执行 Jar 包已为大多数流行的云 PaaS(平台即服务)提供商准备就绪。这些提供商通常要求您“自带容器”。它们管理应用程序进程(不 specifically 是 Java 应用程序),因此它们需要一个中间层,将 您的 应用程序适配到 云端 对运行进程的定义。

Heroku 和 Cloud Foundry 这两个流行的云提供商采用“构建包”方法。构建包将您部署的代码封装在启动应用程序所需的一切中。它可能是一个 JDK 和一个对 java 的调用、一个嵌入式 Web 服务器或一个功能齐全的应用程序服务器。构建包是可插拔的,但理想情况下,您应该尽可能少地对其进行自定义。这减少了不受您控制的功能的占用空间。它最大程度地减少了开发和生产环境之间的差异。

理想情况下,您的应用程序,例如 Spring Boot 可执行 Jar 包,应包含运行所需的一切。

在本节中,我们探讨如何将“入门”部分中开发的应用程序部署到云端并运行。

Cloud Foundry

如果未指定其他构建包,Cloud Foundry 会提供默认构建包。Cloud Foundry Java 构建包对 Spring 应用程序(包括 Spring Boot)提供出色的支持。您可以部署独立的 Java 可执行 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 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 命令验证已部署应用程序的状态,如以下示例所示:

$ 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

  • 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")
	}

	// ...

}

所有 Cloud Foundry 属性都以 vcap 为前缀。您可以使用 vcap 属性访问应用程序信息(例如应用程序的公共 URL)和服务信息(例如数据库凭据)。有关完整详细信息,请参阅 CloudFoundryVcapEnvironmentPostProcessor API 文档。

Java CFEnv 项目更适合配置 DataSource 等任务。

Kubernetes

Spring Boot 通过检查环境变量中的 "*_SERVICE_HOST""*_SERVICE_PORT" 变量来自动检测 Kubernetes 部署环境。您可以使用 spring.main.cloud-platform 配置属性覆盖此检测。

Spring Boot 帮助您管理应用程序状态,并使用 Actuator 的 HTTP Kubernetes Probes 导出它。

Kubernetes 容器生命周期

当 Kubernetes 删除应用程序实例时,关闭过程同时涉及多个子系统:关闭钩子、注销服务、从负载均衡器中移除实例……由于此关闭处理是并行发生的(并且由于分布式系统的性质),因此存在一个时间窗口,在此期间流量可以路由到也已开始其关闭处理的 Pod。

您可以在 preStop 处理器中配置一个休眠执行,以避免请求路由到已开始关闭的 Pod。此休眠时间应足够长,以停止将新请求路由到 Pod,并且其持续时间会因部署而异。

如果您使用的是 Kubernetes 1.32 或更高版本,preStop 处理器可以通过 Pod 配置文件中的 PodSpec 配置,如下所示:

spec:
  containers:
  - name: "example-container"
    image: "example-image"
    lifecycle:
      preStop:
        sleep:
          seconds: 10

如果您尚未使用 Kubernetes 1.32,则可以使用 exec 命令调用 sleep

spec:
  containers:
  - name: "example-container"
    image: "example-image"
    lifecycle:
      preStop:
        exec:
          command: ["sh", "-c", "sleep 10"]
为此,容器需要有一个 shell。

pre-stop 钩子完成后,SIGTERM 将发送到容器,并开始正常关闭,允许任何剩余的正在进行的请求完成。

当 Kubernetes 向 Pod 发送 SIGTERM 信号时,它会等待一个称为终止宽限期(默认为 30 秒)的指定时间。如果容器在宽限期后仍在运行,它们将被发送 SIGKILL 信号并强制移除。如果 Pod 关闭时间超过 30 秒,这可能是因为您增加了 spring.lifecycle.timeout-per-shutdown-phase,请确保通过在 Pod YAML 中设置 terminationGracePeriodSeconds 选项来增加终止宽限期。

Heroku

Heroku 是另一个流行的 PaaS 平台。要自定义 Heroku 构建,您需要提供一个 Procfile,其中包含部署应用程序所需的咒语。Heroku 为 Java 应用程序分配一个 port,然后确保路由到外部 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 实例,然后该实例在启动时使用该端口。$PORT 环境变量由 Heroku PaaS 分配给我们。

这应该是您所需的一切。Heroku 部署最常见的部署工作流程是将代码 git push 到生产环境,如以下示例所示:

$ 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 [email protected]:agile-sierra-1405.git
 * [new branch]      main -> main

您的应用程序现在应该已在 Heroku 上运行。有关更多详细信息,请参阅 在 Heroku 上部署 Spring Boot 应用程序

OpenShift

OpenShift 提供了许多描述如何部署 Spring Boot 应用程序的资源,包括:

Amazon Web Services (AWS)

Amazon Web Services 提供了几种适用于运行基于 Spring Boot 应用程序的选项,无论是作为容器、传统 Web 应用程序 (war) 还是自包含的可执行 jar 文件。流行的选项有:

  • Amazon Elastic Container Service (ECS)

  • AWS Elastic Beanstalk

Amazon Elastic Container Service (ECS)

官方的 Amazon ECS 开发者指南 提供了平台功能的全面概述,并包含 入门指南,其中详细介绍了启动和运行容器所需的步骤。

Spring Boot 应用程序可以使用容器镜像中描述的技术打包到 Docker 容器中。

除了开发人员指南,AWS 还提供了使用 AWS Fargate 在 Amazon ECS 上部署容器化 Java 服务的专题指南

Spring Boot 通过检查环境变量中的 AWS_EXECUTION_ENV 变量来自动检测 AWS ECS 部署环境。您可以使用 spring.main.cloud-platform 配置属性覆盖此检测。

AWS Elastic Beanstalk

如官方 Elastic Beanstalk Java 指南 中所述,部署 Java 应用程序有两种主要选项。您可以使用“Tomcat 平台”或“Java SE 平台”。

使用 Tomcat 平台

此选项适用于生成 war 文件的 Spring Boot 项目。请遵循官方指南和 Tomcat 上的 Java 教程

创建 Spring Boot 应用程序的可部署 war 文件在传统部署中进行了描述。

使用 Java SE 平台

此选项适用于生成 jar 文件并运行嵌入式 Web 容器的 Spring Boot 项目。请遵循官方指南和 Java 教程。还有社区提供的教程,例如 此教程

CloudCaptain 和 Amazon Web Services

CloudCaptain 的工作原理是将您的 Spring Boot 可执行 jar 或 war 文件转换为一个最小的 VM 镜像,该镜像可以在 VirtualBox 或 AWS 上不变地部署。CloudCaptain 深度集成了 Spring Boot,并使用您的 Spring Boot 配置文件中的信息自动配置端口和健康检查 URL。CloudCaptain 利用这些信息来生成镜像以及配置所有提供的资源(实例、安全组、弹性负载均衡器等)。

创建 CloudCaptain 账户,将其连接到您的 AWS 账户,安装最新版本的 CloudCaptain 客户端,并确保应用程序已通过 Maven 或 Gradle 构建(例如,使用 mvn clean package)后,您可以使用类似于以下内容的命令将 Spring Boot 应用程序部署到 AWS:

$ boxfuse run myapp-1.0.jar -env=prod

有关更多选项,请参阅 boxfuse run 文档。如果当前目录中存在 boxfuse.conf 文件,则会考虑该文件。

默认情况下,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 CloudAzure App Service

Google Cloud

Google Cloud 提供了几种可用于启动 Spring Boot 应用程序的选项。最容易上手的使用可能是 App Engine,但您也可以找到使用 Container Engine 在容器中或使用 Compute Engine 在虚拟机上运行 Spring Boot 的方法。

要将您的第一个应用程序部署到 App Engine 标准环境,请按照 此教程 进行操作。

或者,App Engine Flex 要求您创建 app.yaml 文件来描述您的应用程序所需的资源。通常,您将此文件放在 src/main/appengine 中,它应该类似于以下文件:

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 插件),如以下示例所示:

<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 部署(您需要先进行身份验证,否则构建将失败)。

© . This site is unofficial and not affiliated with VMware.