将 Spring Boot 应用程序迁移到 Azure Spring Apps

注意

Azure Spring Apps 是 Azure Spring Cloud 服务的新名称。 虽然该服务有新名称,但一些地方仍会使用旧名称,我们仍在更新屏幕截图、视频和图形等资产。

本指南介绍在想要迁移现有 Spring Boot 应用程序以在 Azure Spring Apps 上运行时应注意的内容。

预迁移

若要确保迁移成功,请在开始之前完成以下各节中所述的评估和清点步骤。

如果无法满足任何预迁移要求,请参阅以下伴随迁移指南:

  • 将可执行的 JAR 应用程序迁移到 Azure Kubernetes 服务上的容器(按指南进行计划)
  • 将可执行的 JAR 应用程序迁移到 Azure 虚拟机(按指南进行计划)

检查应用程序组件

标识本地状态

在 PaaS 环境上,无法保证应用程序在任意给定时间都刚好运行一次。 即使将应用程序配置为在单个实例中运行,在以下情况下也可以创建重复的实例:

  • 由于故障或系统更新,必须将应用程序重新定位到物理主机。
  • 正在更新应用程序。

在上述任一情况下,原始实例将始终保持运行状态,直到新实例完成启动。 对于你的应用程序,这会产生以下潜在的重大影响:

  • 无法保证单一实例真正是单一的。
  • 任何未持久保留到外部存储中的数据丢失都可能远远早于保留在单个物理服务器或 VM 上的数据丢失。

在迁移到 Azure Spring Apps 之前,请确保代码不包含不得丢失或复制的本地状态。 如果存在本地状态,请更改代码,使其在应用程序外部存储该状态。 云就绪应用程序通常将应用程序状态存储在以下位置:

确定是否使用以及如何使用文件系统

查找向本地文件系统写入和/或从中读取服务的任何实例。 确定写入和读取短期/临时文件的位置,以及写入和读取长期文件的位置。

注意

Azure Spring Apps 为每个装载在 /tmpAzure Spring Apps 实例中的临时存储提供 5 GB 的临时存储。 如果临时文件的写入超出了该限制或位于其他位置,则需要进行代码更改。

只读静态内容

如果应用程序当前提供静态内容,则需为其提供一个备用位置。 可能需要考虑将静态内容移到 Azure Blob 存储,并添加 Azure CDN,方便用户在全球范围内快速下载。 有关详细信息,请参阅 Azure 存储中的静态网站托管快速入门:将 Azure 存储帐户与 Azure CDN 集成

动态发布的静态内容

如果应用程序允许那些通过应用程序上传/生成但在创建后不可变的静态内容,则可将上述 Azure Blob 存储和 Azure CDN 与 Azure 函数配合使用,以便处理上传和 CDN 刷新操作。 我们提供了一个示例实现,用于通过 Azure Functions 进行静态内容的上传和 CDN 预加载操作

确定是否有服务包含特定于 OS 的代码

如果应用程序包含的代码有主机 OS 的依赖项,则需重构该代码,删除那些依赖项。 例如,可能需要将文件系统路径中使用的 /\ 替换为 File.SeparatorPaths.get

切换到受支持的平台

Azure Spring Apps 提供特定版本的 Java 和 Spring Boot 和 Spring Cloud 的特定版本。 若要确保兼容性,请在继续执行其余迁移步骤之前,首先将应用程序迁移到当前环境中支持的 Java 版本之一。 务必全面测试生成的配置。 请在此类测试中使用最新且稳定的 Linux 发布版。

注意

如果当前服务器在不受支持的 JDK(如 Oracle JDK 或 IBM OpenJ9)上运行,则此验证尤其重要。

若要获取当前的 Java 版本,请登录到生产服务器并运行以下命令:

java -version

有关受支持的 Java、Spring Boot 和 Spring Cloud 版本以及更新说明,请参阅 准备应用程序以在 Azure Spring Apps 中部署。

确定应用程序是否依赖于计划的作业

计划作业(例如,Quantum 计划程序任务或 Unix cron 作业)不应与 Azure Spring Apps 一起使用。 Azure Spring Apps 不会阻止你在内部部署包含计划任务的应用程序。 但是,如果应用程序横向扩展,则同一个计划的作业可能会按照计划期间运行多次。 这种情况可能会导致意外的后果。

清点在生产服务器上运行的所有计划任务(应用程序代码内部或外部)。

确定 Spring Boot 版本

检查要迁移的每个应用程序的依赖项,以确定其 Spring Boot 版本。

Maven

在 Maven 项目中,通常可以在 POM 文件的 <parent> 元素中找到 Spring Boot 版本:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.10</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
Gradle

在 Gradle 项目中,通常可以在 plugins 部分找到 Spring Boot 版本(作为 org.springframework.boot 插件的版本):

plugins {
  id 'org.springframework.boot' version '2.7.10'
  id 'io.spring.dependency-management' version '1.0.15.RELEASE'
  id 'java'
}

对于使用 Spring Boot 1.x 的任何应用程序,请按照 Spring Boot 2.0 迁移指南将其更新为受支持的 Spring Boot 版本。 有关支持的版本,请参阅准备应用程序以在 Azure Spring Apps 中部署的 Spring Boot 和 Spring Cloud 版本部分。

确定日志聚合解决方案

确定要迁移的应用程序正在使用的任何日志聚合解决方案。 需要在迁移中配置诊断设置,以使记录的事件可供使用。 有关详细信息,请参阅“ 确保控制台日志记录并配置诊断设置 ”部分。

确定应用程序性能管理 (APM) 代理

确定与应用程序一起使用的任何应用程序性能监视代理。 Azure Spring Apps 支持与 Application Insights、New Relic、Elastic APM、Dynatrace 和 AppDynamics 集成。 如果应用程序使用的是受支持的 APM,请在迁移中配置集成。 如果应用程序未使用受支持的 APM,请考虑改用 Application Insights。 有关详细信息,请参阅 “迁移 ”部分。

清点外部资源

标识外部资源,如数据源、JMS 消息代理和其他服务的 URL。 在 Spring Boot 应用程序中,通常可在通常名为 application.properties 或 application.yml 的文件的 src/main/directory 文件夹中找到此类资源的配置

数据库

确定任何 SQL 数据库的连接字符串。

Spring Boot 应用程序的连接字符串通常出现在配置文件中。

下面是 application.properties 文件中的示例:

spring.datasource.url=jdbc:mysql://localhost:3306/mysql_db
spring.datasource.username=dbuser
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

下面是 application.yaml 文件中的示例:

spring:
  data:
    mongodb:
      uri: mongodb://mongouser:deepsecret@mongoserver.contoso.com:27017

有关可能性更大的配置场景,请参阅 Spring 数据文档:

JMS 消息代理

通过在生成清单(通常是 pom.xml 或 build.gradle 文件)中查找相关依赖项,确定所使用的一个或多个代理

例如,使用 ActiveMQ 的 Spring Boot 应用程序通常会在其 pom.xml 文件中包含此依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

使用商业代理的 Spring Boot 应用程序通常直接包含代理的 JMS 驱动程序库的依赖项。 下面是 build.gradle 文件中的示例:

    dependencies {
      ...
      compile("com.ibm.mq:com.ibm.mq.allclient:9.0.4.0")
      ...
    }

确定正在使用的一个或多个代理后,请找到相应的设置。 在 Spring Boot 应用程序中,通常可以在应用程序目录的 application.properties 和 application.yml 文件中找到它们

下面是 application.properties 文件中的 ActiveMQ 示例

spring.activemq.brokerurl=broker:(tcp://localhost:61616,network:static:tcp://remotehost:61616)?persistent=false&useJmx=true
spring.activemq.user=admin
spring.activemq.password=tryandguess

有关 ActiveMQ 配置的详细信息,请参阅 Spring Boot 消息文档

下面是 application.yaml 文件中的 IBM MQ 示例

ibm:
  mq:
    queueManager: qm1
    channel: dev.ORDERS
    connName: localhost(14)
    user: admin
    password: big$ecr3t

有关 IBM MQ 配置的详细信息,请参阅 IBM MQ Spring 组件文档

确定外部缓存

确定正在使用的任何外部缓存。 通常,Redis 是通过 Spring Data Redis 使用的。 有关配置信息,请参阅 Spring Data Redis 文档。

通过搜索相应的配置(在 JavaXML)中,确定是否正在通过 Spring 会话缓存会话数据。

标识提供者

标识应用程序使用的任何标识提供者。 有关可如何配置标识提供者的信息,请参阅以下内容:

识别依赖于非标准端口的所有客户端

Azure Spring Apps 覆盖 server.port 已部署应用程序中的设置。 如果客户的任何客户端依赖于 443 以外的端口上提供的应用程序,则需要对其进行修改。

所有其他的外部资源

本指南不可能记录每个可能的外部依赖项。 迁移后,你将负责验证你能否满足应用程序的所有外部依赖项的要求。

清单配置源和机密

清单密码和安全字符串

检查生产部署上的所有属性和配置文件以及所有环境变量中是否有机密字符串和密码。 在 Spring Boot 应用程序中,通常可以在 application.properties 或 application.yml 文件中找到此类字符串

清点证书

记录用于公共 SSL 终结点或与后端数据库以及其他系统通信的所有证书。 可以通过运行以下命令来查看生产服务器上的所有证书:

keytool -list -v -keystore <path to keystore>

检查部署体系结构

记录每个服务的硬件要求

记录 Spring Boot 应用程序的以下信息:

  • 正在运行的实例数。
  • 为每个实例分配的 CPU 数量。
  • 为每个实例分配的 RAM 量。

记录异地复制/分发

确定 Spring Boot 应用程序实例当前是否分布在多个区域或数据中心。 记录要迁移的应用程序的运行时间要求/SLA。

迁移

创建 Azure Spring Apps 实例和应用

在 Azure 订阅中预配 Azure Spring Apps 实例(如果尚不存在)。 然后在那里创建应用程序。 有关详细信息,请参阅快速入门:将第一个应用程序部署到 Azure Spring Apps

确保控制台日志记录并配置诊断设置

配置日志记录,使所有输出都路由到控制台而不是文件。

将应用程序部署到 Azure Spring Apps 后, 添加诊断设置 ,使记录的事件可供使用,例如通过 Azure Monitor Log Analytics。

LogStash/ELK 堆栈

如果使用 LogStash/ELK 堆栈进行日志聚合,请将诊断设置配置为将控制台输出流式传输到 Azure 事件中心。 然后,使用 LogStash EventHub 插件将记录的事件引入到 LogStash 中。

Splunk

如果使用 Splunk 进行日志聚合,请将诊断设置配置为将控制台输出流式传输到 Azure Blob 存储。 然后,使用 Microsoft 云服务的 Splunk 附加产品将记录的事件引入到 Splunk 中。

配置持久性存储

如果应用程序的任何部分读取或写入到本地文件系统,将需要配置持久性存储来替换本地文件系统。 有关详细信息,请参阅 在 Azure Spring Apps 中使用内置持久存储。

应将任何临时文件写入 /tmp 目录。 要实现 OS 独立性,可以使用 System.getProperty("java.io.tmpdir") 获取此目录。 还可以使用 java.nio.Files::createTempFile 来创建临时文件。

将所有证书迁移到 KeyVault

Azure Spring Apps 不提供对 JRE 密钥存储的访问权限,因此必须将证书迁移到 Azure KeyVault,并更改应用程序代码以访问 KeyVault 中的证书。 有关详细信息,请参阅 Key Vault 证书入门适用于 Java 的 Azure Key Vault 证书客户端库

配置应用程序性能管理 (APM) 集成

Azure Spring Apps 提供以下 APM 集成。 按照链接启用所需的 APM。

如果应用程序未使用受支持的 APM,请考虑改用 Application Insights。 Azure Spring Apps 提供与 Application Insights 的深度集成,用于对性能管理和对异常的实时响应。

在应用程序中禁用指标客户端和终结点

删除应用程序中使用的任何指标客户端或应用程序中公开的任何指标终结点。

部署应用

部署每个已迁移的微服务(不包括 Spring Cloud 配置和注册表服务器),如快速入门中所述 :将第一个应用程序部署到 Azure Spring Apps

配置基于服务的机密和外部化设置

可以将任何基于服务的配置设置作为环境变量注入每个服务。 在 Azure 门户中,使用以下步骤:

  1. 导航到 Azure Spring Apps 实例并选择“ 应用”。
  2. 选择要配置的服务。
  3. 选择“配置”。
  4. 输入要配置的变量。
  5. 选择“保存”。

Spring Cloud App Configuration Settings

迁移和启用标识提供者

如果任何 Spring Cloud 应用程序需要身份验证或授权,请确保将其配置为访问标识提供者:

  • 如果标识提供者是 Microsoft Entra ID,则无需更改。
  • 如果标识提供者是本地 Active Directory林,请考虑使用 Microsoft Entra ID 实现混合标识解决方案。 有关详细信息,请参阅混合标识文档
  • 如果标识提供者是另一个本地解决方案(例如 PingFederate),请参阅 Microsoft Entra 连接 主题的自定义安装,以配置与 Microsoft Entra ID 的联合。 或者,考虑使用 Spring 安全性通过 OAuth2/OpenID ConnectSAML 来使用标识提供者。

公开应用程序

默认情况下,部署到 Azure Spring Apps 的应用程序在外部不可见。 可通过以下命令公开应用程序:

az spring app update --name <application name> --is-public true

如果使用或打算使用 Spring Cloud Gateway,请跳过此步骤。 有关详细信息,请参阅以下部分。

迁移后

现在你已完成迁移,请验证应用程序是否按预期运行。 然后可借助以下建议,提高应用程序的云原生性。

  • 请考虑将应用程序与 Spring Cloud 注册表配合使用。 这将使应用程序能够由其他已部署的 Spring 应用程序和客户端动态发现。 有关详细信息,请参阅 准备应用程序以在 Azure Spring Apps 中部署。 然后修改任何应用程序客户端,以使用 Spring Client 负载均衡器。 这样,客户端就可以获取应用程序所有正在运行的实例的地址,并在另一个实例损坏或无响应时查找有效实例。 有关详细信息,请参阅 Spring 使用技巧:Spring Blog 中的 Spring Cloud 负载均衡器

  • 请考虑添加 Spring Cloud 网关实例,而不是公开你的应用程序。 Spring Cloud Gateway 为 Azure Spring Apps 实例中部署的所有应用程序提供单个终结点。 如果已部署 Spring Cloud 网关,请确保将其配置为将流量路由到新部署的应用程序。

  • 请考虑添加 Spring Cloud 配置服务器,以集中管理和版本控制配置所有 Spring Cloud 应用程序。 首先,创建 Git 存储库来容纳配置,并将 Azure Spring Apps 实例配置为使用它。 有关详细信息,请参阅为服务设置 Spring Cloud 配置服务器实例。 然后使用以下步骤迁移配置:

    1. 在应用程序的 src/main/resources 目录内,创建一个包含以下内容的 bootstrap.yml 文件

        spring:
          application:
            name: <your-application-name>
      
    2. 在配置 Git 存储库中<,创建 application-name.yml> 文件,该文件your-application-name与上一步相同。 将设置从 src/main/resources 中的 application.yml 文件移动到刚创建的新文件。 如果这些设置以前在 .properties 文件中,则先将其转换为 YAML。 可以查找联机工具或 IntelliJ 插件来执行此转换。

    3. 在上述目录中创建一个 application.yml 文件。 可以使用此文件定义将在 Azure Spring Apps 实例上的所有应用程序之间共享的设置和资源。 此类设置通常包括数据源、日志记录设置、Spring Boot Actuator 配置等。

    4. 提交这些更改并将其推送到 Git 存储库。

    5. 从应用程序中删除 application.properties 或 application.yml 应用程序

  • 请考虑为自动、一致的部署添加部署管道。 提供有关 Azure PipelinesGitHub ActionsJenkins 的说明。

  • 请考虑使用过渡部署在生产中测试代码更改,然后再将其提供给一些或所有最终用户。 有关详细信息,请参阅在 Azure Spring Apps 中设置过渡环境

  • 请考虑添加服务绑定,以便将应用程序连接到受支持的 Azure 数据库。 如果使用这些服务绑定,则无需向 Spring Cloud 应用程序提供连接信息(包括凭据)。

  • 请考虑使用 Azure 应用程序 Insights 监视应用程序的性能和交互。 有关详细信息,请参阅 Azure Spring Apps 中的 Application Insights Java 进程内代理

  • 请考虑添加 Azure Monitor 预警规则和操作组,以快速检测并解决异常情况。 有关详细信息,请参阅 教程:使用警报和操作组监视 Spring Cloud 资源。

  • 请考虑副本 (replica)另一个区域中的 Azure Spring Apps 部署,以提高延迟和更高的可靠性和容错能力。 使用 Azure 流量管理器在部署之间实现负载均衡,或使用 Azure Front Door 添加 SSL 卸载和具有 DDoS 防护的 Web 应用程序防火墙。

  • 如果不需要异地复制,请考虑添加 Azure 应用程序网关,以便添加 SSL 卸载和具有 DDoS 防护的 Web 应用程序防火墙。