将 Spring Cloud 应用程序迁移到 Azure 容器应用

本指南介绍在需要迁移现有 Spring Cloud 应用程序以使之在 Azure 容器应用上运行时应注意的事项。

预迁移

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

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

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

检查应用程序组件

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

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

Azure 容器应用提供多种类型的存储。 临时存储可以读写临时数据,并可供运行中的容器或副本使用。 Azure 文件提供永久存储,并且可跨多个容器共享。 有关详细信息,请参阅在 Azure 容器应用中使用存储装载

只读静态内容

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

动态发布的静态内容

如果应用程序支持静态内容,无论是上传的内容还是由应用程序本身生成的内容,且在创建后保持不变,则可以集成 Azure Blob 存储和 Azure CDN。 还可以使用 Azure Function 来管理上传,并在必要时触发 CDN 刷新。 我们提供了一个示例实现,用于通过 Azure Functions 进行静态内容的上传和 CDN 预加载操作

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

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

切换到受支持的平台

如果手动创建 Dockerfile 并将容器化应用程序部署到 Azure 容器应用,则可以完全控制部署,包括 JRE/JDK 版本。

对于从项目进行部署,Azure 容器应用还提供特定版本的 Java(8、11、17 和 21)以及特定版本的 Spring Boot 和 Spring Cloud 组件。 若要确保兼容性,请在继续执行其余迁移步骤之前,首先将应用程序迁移到当前环境中支持的 Java 版本之一。 务必全面测试生成的配置。 请在此类测试中使用最新且稳定的 Linux 发布版。

注意

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

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

java -version

有关支持的 Java、Spring Boot 和 Spring Cloud 版本以及更新说明,请参阅 Azure 容器应用上的 Java 概述

确定 Spring Boot 版本

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

Maven

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

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

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

plugins {
  id 'org.springframework.boot' version '3.3.3'
  id 'io.spring.dependency-management' version '1.1.6'
  id 'java'
}

对于使用 Spring Boot 3.x 之前版本的任何应用程序,请遵循 Spring Boot 2.0 迁移指南Spring Boot 3.0 迁移指南,将其更新到受支持的 Spring Boot 版本。 有关支持的版本,请参阅 Spring Cloud 文档。

确定 Spring Cloud 版本

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

Maven

在 Maven 项目中,Spring Cloud 版本通常在 spring-cloud.version 属性中设置:

  <properties>
    <spring-cloud.version>2023.0.2</spring-cloud.version>
  </properties>
Gradle

在 Gradle 项目中,Spring Cloud 版本通常在“额外属性”块中设置:

ext {
  set('springCloudVersion', "2023.0.2")
}

你需要更新所有应用程序才能使用受支持的 Spring Cloud 版本。 有关支持的版本,请参阅 Spring Cloud 文档。

确定日志聚合解决方案

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

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

确定应用程序使用的任何应用程序性能管理代理。 Azure 容器应用不提供对 APM 集成的内置支持。 需要准备好容器镜像或将 APM 工具直接集成到代码中。 如果要衡量应用程序的性能,但尚未集成任何 APM,则可以考虑使用 Azure Application Insights。 有关详细信息,请参阅迁移部分。

清点外部资源

标识外部资源,如数据源、JMS 消息代理和其他服务的 URL。 在 Spring Cloud 应用程序中,通常可以在以下位置之一找到此类资源的配置:

  • src/main/resources 文件夹中,位于通常称为 application.propertiesapplication.yml 的文件中。
  • 在你在上一步中确定的 Spring Cloud Config Server 存储库中。

数据库

对于 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.4.0.5")
      ...
    }

确定正在使用的一个或多个代理后,请找到相应的设置。 在 Spring Cloud 应用程序中,通常可以在应用程序目录的 application.propertiesapplication.yml 中找到,或在 Spring Cloud Config Server 存储库中找到。

注意

Microsoft 建议使用最安全的可用身份验证流。 此过程中所述的身份验证流(例如数据库、缓存、消息传送或 AI 服务)需要高度信任应用程序,并且存在其他流中不存在的风险。 仅当更安全的选项(例如无密码连接或无密钥连接的托管标识)不可行时,才使用此流。 对于本地计算机操作,首选无密码连接或无密钥连接的用户标识。

下面是 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=<password>

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

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

ibm:
  mq:
    queueManager: qm1
    channel: dev.ORDERS
    connName: localhost(14)
    user: admin
    password: <password>

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

确定外部缓存

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

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

标识提供者

标识需要身份验证和/或授权的所有标识提供者和所有 Spring Cloud 应用程序。 有关如何配置标识提供者的信息,请参阅以下资源:

通过 VMware Tanzu 应用程序服务(TAS,之前称为 Pivotal Cloud Foundry)配置的资源

对于使用 TAS 托管的应用程序,通常通过 TAS 服务绑定配置外部资源(包括前面所述的资源)。 若要检查此类资源的配置,请使用 TAS (Cloud Foundry) CLI 查看应用程序的 VCAP_SERVICES 变量。

# Log into TAS, if needed (enter credentials when prompted)
cf login -a <API endpoint>

# Set the organization and space containing the application, if not already selected during login.
cf target org <organization name>
cf target space <space name>

# Display variables for the application
cf env <Application Name>

检查绑定到应用程序的外部服务配置设置的 VCAP_SERVICES 变量。 有关详细信息,请参阅 TAS (Cloud Foundry) 文档

所有其他的外部资源

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

清单配置源和机密

清单密码和安全字符串

检查生产部署上的所有属性和配置文件以及所有环境变量中是否有机密字符串和密码。 在 Spring Cloud 应用程序中,通常可以在各个服务的 application.propertiesapplication.yml 文件中找到此类字符串,或在 Spring Cloud Config Server 存储库中找到此类字符串。

清点证书

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

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

确定是否使用 Spring Cloud Vault

如果使用 Spring Cloud Vault 来存储和访问机密,请标识备用机密存储(例如,HashiCorp Vault 或 CredHub)。 然后标识应用程序代码使用的所有机密。

查找配置服务器源

如果应用程序使用 Spring Cloud Config Server,请确定配置的存储位置。 通常可以在 bootstrap.ymlbootstrap.properties 文件中找到此设置,有时也可以在 application.ymlapplication.properties 文件中找到此设置。 设置如下所示:

spring.cloud.config.server.git.uri: file://${user.home}/spring-cloud-config-repo

尽管 git 最常用作 Spring Cloud Config Server 的备用数据存储(如前文所述),但也可能使用一种其他的后端。 请参阅 Spring Cloud Config Server 文档,了解有关其他后端的信息,如关系数据库 (JDBC)SVN本地文件系统

检查部署体系结构

记录每个服务的硬件要求

对于每个 Spring Cloud 服务(不包括配置服务器、注册表或网关),记录以下信息:

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

记录异地复制/分发

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

确定绕过服务注册表的客户端

确定调用任何要迁移的服务的客户端应用程序,而无需使用 Spring Cloud 服务注册表。 迁移后,将无法再进行此类调用。 更新此类客户端,以便在迁移前使用 Spring Cloud OpenFeign

迁移

删除受限配置

Azure 容器应用环境提供托管的 Eureka Server、Spring Cloud Config Server 和 Admin。当应用程序绑定到 Java 组件时,Azure 容器应用会将相关属性作为系统环境变量注入。 根据 Spring Boot 外部化配置设计,在代码中定义或打包在项目中的应用程序属性会被系统环境变量覆盖。

如果通过命令行参数、Java 系统属性或容器的环境变量设置了以下属性之一,则必须将其删除,以避免冲突和意外行为:

  • SPRING_CLOUD_CONFIG_COMPONENT_URI
  • SPRING_CLOUD_CONFIG_URI
  • SPRING_CONFIG_IMPORT
  • eureka.client.fetch-registry
  • eureka.client.service-url.defaultZone
  • eureka.instance.prefer-ip-address
  • eureka.client.register-with-eureka
  • SPRING_BOOT_ADMIN_CLIENT_INSTANCE_PREFER-IP
  • SPRING_BOOT_ADMIN_CLIENT_URL

创建 Azure 容器应用托管环境和应用

在现有托管环境的 Azure 订阅中配置 Azure 容器应用,或为要迁移的每个服务创建一个新环境。 无需创建作为 Spring Cloud 注册表和配置服务器运行的应用。 更多信息,请参阅快速入门:使用 Azure 门户部署你的第一个应用程序

准备 Spring Cloud Config Server

在适用于 Spring 的 Azure 容器应用中配置 Config 服务器。 有关详细信息,请参阅在 Azure 容器应用中为 Config Server for Spring 组件配置设置

注意

如果当前的 Spring Cloud Config 存储库位于本地文件系统或本地,则首先需要将配置文件迁移或复制到基于云的资源库,如 GitHub、Azure Repos 或 BitBucket。

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

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

将应用程序部署到 Azure 容器应用之后,可以在容器应用环境中配置日志选项,以定义一个或多个日志目标。 这些目标可以包括 Azure Monitor Log Analytics、Azure 事件中心,甚至其他第三方监控解决方案。 还可以选择禁用日志数据,并且只在运行时查看日志。 有关详细配置说明,请参阅 Azure 容器应用中的日志存储和监控选项

配置持久性存储

如果应用程序的任何部分要读写本地文件系统,则需要配置持久性存储来替代本地文件系统。 可以通过应用程序设置指定装载到容器中的路径,并将其与应用正在使用的路径保持一致。 有关详细信息,请参阅在 Azure 容器应用中使用存储装载

将 Spring Cloud Vault 机密迁移到 Azure KeyVault

可以使用 Azure KeyVault Spring Boot 起动器,通过 Spring 将机密直接注入到应用程序。 有关详细信息,请参阅如何使用适用于 Azure Key Vault 的 Spring Boot 起动器

注意

迁移可能需要对一些机密重命名。 请相应地更新应用程序代码。

将所有证书迁移到 KeyVault

Azure 容器应用支持应用之间的安全通信。 应用程序无需管理建立安全通信的过程。 可以将私人证书上传到 Azure 容器应用,或使用 Azure 容器应用提供的免费托管证书。 建议使用 Azure Key Vault 来管理证书。 有关详细信息,请参阅 Azure 容器应用中的证书

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

如果已经在容器中配置了 APM 相关变量,则只需确保可以建立与目标 APM 平台的连接。 如果 APM 配置引用了容器中的环境变量,则需要在 Azure 容器应用上相应地设置运行时环境变量。 连接字符串等敏感信息应安全处理。 可以将其指定为机密,也可以引用存储在 Azure Key Vault 中的机密。

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

可以将配置设置作为环境变量注入每个容器。 变量中的任何更改都会为现有应用创建一个新版本。 机密是键值对,在所有版本中都有效。

迁移和启用标识提供者

如果有任何 Spring Cloud 应用程序需要身份验证或授权,请遵照以下指导原则确保它们已配置为访问标识提供程序:

  • 如果标识提供者是 Microsoft Entra ID,则不需要进行任何更改。
  • 如果标识提供者是本地 Active Directory 林,请考虑使用 Microsoft Entra ID 实现混合标识解决方案。 有关指南,请参阅混合标识文档
  • 如果标识提供者是另一个本地解决方案(如 PingFederate),请参阅 Microsoft Entra Connect 的自定义安装主题,以配置与 Microsoft Entra ID 的联合身份验证。 或者,考虑使用 Spring 安全性通过 OAuth2/OpenID ConnectSAML 来使用标识提供者。

更新客户端应用程序

更新所有客户端应用程序的配置,将已发布的 Azure 容器应用终结点用于迁移的应用程序。

迁移后

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

  • 请考虑将应用程序与 Spring Cloud 注册表配合使用。 此组件可让其他已部署的 Spring 应用程序和客户端动态发现你的应用程序。 有关详细信息,请参阅 在 Azure 容器应用中为 Eureka Server for Spring 组件配置设置。 然后,修改任何应用程序客户端以使用 Spring 客户端负载均衡器。 Spring Client 负载均衡器使客户端能够获取应用程序所有运行实例的地址,并在另一个实例损坏或无响应时找到可以运行的实例。 有关详细信息,请参阅 Spring 博客中的 Spring 提示:Spring 云负载均衡器

  • 请考虑添加 Spring Cloud 网关实例,而不是公开你的应用程序。 Spring Cloud Gateway 可为部署在 Azure 容器应用环境中的所有应用程序提供单一终结点。 如果已经部署了 Spring Cloud Gateway,请确保配置了路由规则,以便将流量路由到新部署的应用程序。

  • 考虑添加 Spring Cloud Config Server,以便集中管理所有 Spring Cloud 应用程序的配置并对其进行版本控制。 首先,创建一个 Git 存储库来存放配置,并配置应用程序实例来使用它。 有关详细信息,请参阅在 Azure 容器应用中为 Config Server for Spring 组件配置设置。 然后使用以下步骤迁移配置:

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

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

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

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

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

  • 考虑添加 Admin for Spring 托管组件,为公开执行器终结点的 Spring Boot Web 应用程序启用管理界面。 有关详细信息,请参阅在 Azure 容器应用中配置 Spring Boot 控制台组件

  • 请考虑为自动、一致的部署添加部署管道。 为 Azure 管道GitHub 操作均提供了说明。

  • 请考虑使用容器应用修订、修订标签和入口流量权重来实现蓝绿部署,这样就能在生产中测试代码变更,然后再将其提供给部分或全部最终用户。 有关详细信息,请参阅 Azure 容器应用中的蓝绿部署

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

  • 请考虑启用 Java 开发堆栈来收集应用程序的 JVM 核心指标。 有关详细信息,请参阅 Azure 容器应用中 Java 应用的 Java 指标

  • 请考虑添加 Azure Monitor 预警规则和操作组,以快速检测并解决异常情况。 有关详细信息,请参阅在 Azure 容器应用中设置警报

  • 请考虑通过启用 Azure 容器应用区域冗余,在区域内跨区域复制应用。 如果发生区域中断,流量会负载均衡并自动路由到副本。 有关冗余设置的详细信息,请参阅 Azure 容器应用中的可靠性

  • 请考虑通过在应用程序网关上使用 Web 应用程序防火墙来保护 Azure 容器应用免受常见漏洞的攻击。 有关详细信息,请参阅使用应用程序网关上的 Web 应用程序防火墙保护 Azure 容器应用

  • 如果应用程序使用旧版 Spring Cloud Netflix 组件,请考虑将其替换为当前的替代组件,如下表所示:

    旧的 当前
    Spring Cloud Eureka Spring Cloud 服务注册表
    Spring Cloud Netflix Zuul Spring Cloud 网关
    Spring Cloud Netflix Archaius Spring Cloud 配置服务器
    Spring Cloud Netflix 功能区 Spring Cloud 负载均衡器(客户端负载均衡器)
    Spring Cloud Hystrix Spring Cloud 断路器 + Resilience4J
    Spring Cloud Netflix Turbine Micrometer + Prometheus