你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 Java 的可靠 Web 应用模式

Azure 应用服务
Azure Front Door

本文提供了实现可靠 Web 应用模式的指导。 此模式概述了如何修改(重新平台化)Web 应用以进行云迁移。 它提供了与架构良好的框架原则相一致的规范性体系结构、代码和配置指导。

为什么采用适用于 Java 的可靠 Web 应用模式?

可靠 Web 应用模式是一套原则和实现技术,它定义了迁移到云时应如何重新平台化 Web 应用。 它重点关注在云中取得成功所需的最低限度代码更新。 以下指南以参考实施为例,介绍了虚构公司 Contoso Fiber 的平台重构历程,为你的历程提供业务背景。 在实施适用于 Java 的可靠 Web 应用模式之前,Contoso Fiber 有一个使用 Spring Boot 框架的单体内部客户帐户管理系统 (CAMS)。

提示

GitHub 徽标。有一个可靠 Web 应用模式的参考实现(示例)。 它表示可靠 Web 应用实现的最终状态。 它是一个生产级 Web 应用,具有本文讨论的所有代码、体系结构和配置更新。 部署并使用参考实现来指导你实现可靠 Web 应用模式。

如何实现可靠 Web 应用模式

本文包括实现可靠 Web 应用模式的体系结构、代码和配置指导。 使用以下链接导航到所需的具体指导:

  • 业务背景:将此指导与业务背景相匹配,并学习如何确定推动重新平台化决策的近期和长期目标。
  • 体系结构指导:了解如何选择正确的云服务并设计符合业务要求的体系结构。
  • 代码指导:实现三种设计模式来提高云中 Web 应用的可靠性和性能效率:重试、断路器和缓存端模式
  • 配置指导:配置身份验证和授权、托管标识、权限化环境、基础结构即代码和监控。

▪ 业务上下文

Web 应用重新平台化的第一步是确定业务目标。 应为 Web 应用程序设定近期目标,如服务水平目标和成本优化目标,以及未来目标。 这些目标会影响对云服务和云中 Web 应用体系结构的选择。 为 Web 应用定义目标 SLO,例如 99.9% 的正常运行时间。 计算影响 Web 应用可用性的所有服务的复合 SLA

例如,一家虚构的公司 Contoso Fiber 希望将其内部客户管理系统 (CAMS) Web 应用扩展到其他地区。 为了满足 Web 应用日益增长的需求,他们制定了以下目标:

  • 应用低成本、高价值的代码更改
  • 服务级别目标 (SLO) 达到 99.9%
  • 采用 DevOps 做法
  • 创建成本优化的环境
  • 提高可靠性和安全性

Contoso Fiber 认为,他们的内部基础结构不是一个经济高效的应用程序扩展解决方案。 因此,他们决定将 CAMS Web 应用程序迁移到 Azure,认为这才是实现当下和未来目标最经济高效的方法。

体系结构指南

可靠 Web 应用模式有几个基本的体系结构要素。 需要使用 DNS 来管理终结点解析,需要 Web 应用程序防火墙来阻止恶意 HTTP 流量,还需要负载均衡器来保护和路由入站用户请求。 应用程序平台托管 Web 应用代码,并通过虚拟网络中的专用终结点来调用所有后端服务。 应用程序性能监控工具可捕获指标和日志,以了解 Web 应用。

显示了可靠 Web 应用模式基本体系结构要素的示意图。

图 1. 可靠 Web 应用模式的基本体系结构要素。

设计体系结构

设计基础结构以支持恢复指标,如恢复时间目标 (RTO) 和恢复点目标 (RPO)。 RTO 会影响可用性,并且必须支持你的 SLO。 确定恢复点目标 (RPO),并配置数据冗余以满足 RPO。

  • 选择基础设施的可靠性。 确定满足可用性需求所需的可用性区域和区域数量。 添加可用性区域和区域,直到复合 SLA 符合你的 SLO。 可靠 Web 应用模式支持多个区域,以实现主动-主动或主动-被动配置。 例如,参考实现采用主动-被动配置,以满足 99.9% 的 SLO 要求。

    对于多区域 Web 应用,可根据业务需要配置负载均衡器,将流量路由到第二个区域,以支持主动-主动或主动-被动配置。 这两个区域需要相同的服务,只是其中一个区域有一个连接各区域的中心虚拟网络。 采用中心辐射型网络拓扑来集中和共享资源,如网络防火墙。 如果有虚拟机,请在中心虚拟网络中添加一台堡垒主机,以便安全地管理虚拟机(请参阅图 2)。

    显示了可靠 Web 应用模式与第二个区域和中心辐射型拓扑的示意图。

    图 2. 可靠 Web 应用模式与第二个区域和中心辐射型拓扑。

  • 选择网络拓扑。 根据 Web 和网络要求选择正确的网络拓扑。 如果计划拥有多个虚拟网络,请使用中心辐射型网络拓扑。 它通过与本地和虚拟网络的混合连接选项,提供成本、管理和安全方面的优势。

挑选正确的 Azure 服务

将 Web 应用转移到云中时,应选择符合业务要求并与本地 Web 应用当前功能相匹配的 Azure 服务。 这种一致性有助于尽可能减少重新架构的工作。 例如,使用可以保持相同数据库引擎并支持现有中间件和框架的服务。 以下各部分提供了为 Web 应用选择合适的 Azure 服务的指导。

例如,在迁移到云之前,Contoso Fiber 的 CAMS Web 应用是一个本地整体 Java Web 应用。 这是一个带有 PostgreSQL 数据库的 Spring Boot 应用。 Web 应用是一款业务线支持应用。 它是面向员工的。 Contoso Fiber 员工使用该应用程序管理来自客户的支持案例。 Web 应用面临可伸缩性和功能部署方面的常见挑战。 基于这一出发点及其业务目标,SLO 推动他们做出了服务选择。

  • 应用程序平台:使用 Azure 应用程序服务作为应用程序平台。 Contoso Fiber 选择“Azure 应用程序服务”作为应用程序平台,原因如下:

    • 自然进展:Contoso Fiber 在其内部部署服务器上部署了 Spring Boot jar 文件,并希望最大限度地减少该部署模型的重新架构工作量。 应用程序服务为运行 Spring Boot 应用提供了强大的支持,因此 Contoso Fiber 自然而然地选择了应用程序服务。 Azure Container Apps 也是此应用的一个有吸引力的替代方法。 有关详细信息,请参阅什么是 Azure Spring Apps?Azure 容器应用概述
    • 高 SLA:它具有满足生产环境要求的高 SLA。
    • 降低管理开销:这是一项完全托管的托管解决方案。
    • 容器化功能:应用程序服务适用于专用容器映像注册表(例如 Azure 容器注册表)。 Contoso Fiber 将来可以使用这些注册表对 Web 应用进行容器化。
    • 自动缩放:Web 应用可以根据用户流量自动进行纵向扩缩和横向扩缩。
  • 标识管理:使用 Microsoft Entra ID 作为标识和访问管理解决方案。 Contoso Fiber 选择 Microsoft Entra ID 的原因如下:

    • 身份验证和授权:这些应用程序需要对呼叫中心员工进行身份验证和授权。
    • 可缩放:可缩放以支持更大的场景。
    • 用户标识控制:呼叫中心员工可以使用其现有的企业标识。
    • 授权协议支持:支持将 OAuth 2.0 用于托管标识。
  • 数据库:使用可保持相同数据库引擎的服务。 使用数据存储决策树。 Contoso Fiber 出于以下原因选择了 Azure Database for PostgreSQL 和灵活的服务器选项:

    • 可靠性:灵活服务器部署模型支持跨多个可用性区域的区域冗余高可用性。 此配置在同一 Azure 区域中的不同可用性区域中维护温备用服务器。 此配置将数据同步复制到备用服务器。
    • 跨区域复制:它具有只读副本功能,可用于将数据异步复制到另一个区域中的只读副本数据库
    • 性能:它提供可预测的性能和智能优化,使用实际使用情况数据来提高数据库性能。
    • 降低管理开销:它是一项完全托管的 Azure 服务,减少了管理工作量。
    • 迁移支持:它支持从本地单服务器 PostgreSQL 数据库进行数据库迁移。 他们可以使用迁移工具来简化迁移过程。
    • 与本地配置的一致性:它支持 不同的社区版本的 PostgreSQL,包括 Contoso Fiber 目前使用的版本。
    • 复原能力。 灵活服务器部署会自动创建服务器备份,并将其存储在同一区域内的区域冗余存储 (ZRS) 上。 它们可以将数据库还原到其备份保留期内的任意时间点。 与 Contoso Fiber 在内部创建的 RPO(可接受的数据丢失量)相比,该备份和还原功能可创建更好的 RPO。
  • 应用程序性能监视:使用 Application Insights 来分析应用程序的遥测数据。 Contoso Fiber 选择使用 Application Insights 的原因如下:

    • 与 Azure Monitor 集成:提供与 Azure Monitor 的最佳集成。
    • 异常情况检测:自动检测性能异常情况。
    • 故障排除:帮助诊断正在运行的应用中的问题。
    • 监视:收集有关用户如何使用应用的信息,并可轻松跟踪自定义事件。
    • 可见性差距:本地解决方案没有应用程序性能监视解决方案。 Application Insights 提供与应用程序平台和代码的轻松集成。
  • 缓存:选择是否在 Web 应用体系结构中添加缓存。 Azure Cache for Redis 是 Azure 的主要缓存解决方案。 它是一个基于 Redis 软件的托管内存中数据存储。 Contoso Fiber 出于以下原因添加了 Azure Redis 缓存:

    • 速度和量:它具有高数据吞吐量和低延迟读取,适用于经常访问的、更改缓慢的数据。
    • 多样化的可支持性:它是 Web 应用的所有实例可使用的统一缓存位置。
    • 外部数据存储。 本地应用程序服务器执行 VM 本地缓存。 此设置未卸载频繁使用的数据,并且无法使数据失效。
    • 非粘性会话:缓存允许 Web 应用程序将会话状态外部化,并使用非粘性会话。 大多数在本地运行的 Java Web 应用都使用内存中客户端缓存。 内存中客户端缓存无法很好地缩放,并增加了主机上的内存占用量。 通过使用 Azure Cache for Redis,Contoso Fiber 获得了全面托管的可缩放缓存服务,从而提高了应用程序的可伸缩性和性能。 Contoso Fiber 使用的是缓存抽象框架 (Spring Cache),只需对配置进行极小的改动即可更换缓存提供程序。 有了它,他们能够从 Ehcache 提供程序切换到 Redis 提供程序。
  • 负载均衡器:使用 PaaS 解决方案的 Web 应用程序应使用 Azure Front Door、Azure 应用程序网关或根据 Web 应用体系结构和要求同时使用这两者。 使用负载均衡器决策树来选取正确的负载均衡器。 Contoso Fiber 需要一个 7 层负载均衡器,该负载均衡器可以跨多个区域路由流量。 Contoso Fiber 需要一个多区域 Web 应用来实现 99.9% 的 SLO。 Contoso Fiber出于以下原因选择了 Azure Front Door

    • 全局负载均衡:一个 7 层负载均衡器,可以跨多个区域路由流量。
    • Web 应用程序防火墙:以本机方式与 Azure Web 应用程序防火墙集成。
    • 路由灵活性:允许应用程序团队配置入口需求,以支持未来应用程序中的更改。
    • 流量加速:使用任意广播访问最近的 Azure 接入点,并找到通往 Web 应用的最快途径。
    • 自定义域:支持具有灵活域验证的自定义域名。
    • 运行状况探测:应用程序需要智能运行状况探测监视。 Azure Front Door 会根据这些探测响应来确定用于路由客户端请求的最佳源。
    • 监视支持:支持内置报告,并为 Front Door 和安全模式提供一体式仪表板。 可以配置与 Azure Monitor 集成的警报。 它允许应用程序记录每个请求和失败的运行状况探测。
    • DDoS 保护:具有内置的 3-4 层 DDoS 保护。
    • 内容分发网络:将 Contoso Fiber 定位为使用内容分发网络。 内容分发网络提供站点加速。
  • Web 应用程序防火墙:使用Azure Web 应用程序防火墙提供集中防护,防止常见的网络攻击和漏洞。 Contoso Fiber 出于以下原因使用了 Azure Web 应用程序防火墙:

    • 全局保护:提供改进的全局 Web 应用保护,而不会降低性能。
    • 僵尸网络防护:团队可以监控和配置设置,以解决与僵尸网络有关的安全问题。
    • 与本地保持一致:本地解决方案在 IT 部门管理的 Web 应用程序防火墙后面运行。
    • 易于使用:Web 应用程序防火墙与 Azure Front Door 集成。
  • 机密管理器:如果要在 Azure 中管理机密,请使用 Azure Key Vault。 Contoso Fiber 出于以下原因使用了密钥保管库:

    • 加密:支持静态加密和传输中加密。
    • 托管标识支持:应用程序服务可以使用托管标识来访问机密存储。
    • 监视和日志记录:有助于审核访问,并在存储的机密发生更改时生成警报。
    • 集成:提供与 Azure 配置存储(应用配置)和 Web 托管平台(应用程序服务)的原生集成。
  • 终结点安全:使用 Azure 专用链接通过虚拟网络中的专用终结点来访问平台即服务解决方案。 虚拟网络与服务之间的流量将遍历 Microsoft 主干网络。 Contoso Fiber 选择专用链接的原因如下:

    • 增强安全通信:它允许应用程序以专用方式访问 Azure 平台上的服务,并减少数据存储的网络占用,以帮助防止数据泄露。
    • 最少的工作量:专用终结点支持 Web 应用平台和 Web 应用使用的数据库平台。 这两个平台都生成了现有本地配置的镜像,以尽量减少更改。
  • 网络安全:使用 Azure 防火墙在网络层面控制入站和出站流量。 使用 Azure Bastion 可安全地连接到虚拟机,而无需公开 RDP/SSH 端口。 Contoso Fiber 采用中心辐射型网络拓扑,并希望将共享网络安全服务置于中心。 Azure 防火墙通过检查支路的所有出站流量来提高网络安全,从而提高安全性。 Contoso Fiber 需要 Azure Bastion 才能从 DevOps 子网中的跳板机进行安全部署。

代码指导

要将 Web 应用成功转移到云中,则需要使用重试模式、断路器模式和缓存端设计模式来更新 Web 应用代码。

显示了基本可靠 Web 应用体系结构中设计模式角色的示意图。

图 3. 设计模式的角色。

每种设计模式都能提供工作负荷设计方面的优势,这些优势与“架构良好的框架”的一个或多个支柱相一致。 以下是应该实现的模式概览:

  1. 重试模式:重试模式通过重试可能间歇性失败的操作来处理暂时性故障。 在对其他 Azure 服务的所有向外呼叫中实现此模式。

  2. 断路器模式:断路器模式可防止应用程序重试非暂时性操作。 在对其他 Azure 服务的所有向外调用中执行此模式。

  3. 缓存端模式:缓存端模式比数据存储更频繁地向缓存添加数据和从缓存检索数据。 在请求数据库时实现此模式。

设计模式 可靠性 (RE) 安全性 (SE) 成本优化 (CO) 卓越运营 (OE) 性能效率 (PE) 支持 WAF 原则
重试模式 RE:07
断路器模式 RE:03
RE:07
PE:07
PE:11
缓存端模式 RE:05
PE:08
PE:12

实现重试模式

在应用程序代码中添加重试模式,以解决临时服务中断问题。 这些中断被称为暂时性故障。 暂时性故障通常会在几秒钟内自行解决。 重试模式允许重新发送失败的请求。 它还允许配置请求延迟和失败前的尝试次数。

使用轻量级容错库 Resilience4j 在 Java 中实现重试模式。 例如,参考实现通过使用重试批注修饰服务计划控制器的 listServicePlans 方法来添加重试模式。 如果初始调用失败,该代码将重试对数据库中服务计划列表的调用。 参考实现配置重试策略,包括最大尝试次数、等待持续时间以及应重试的异常。 重试策略在 application.properties 中配置。

    @GetMapping("/list")
    @PreAuthorize("hasAnyAuthority('APPROLE_AccountManager')")
    @CircuitBreaker(name = SERVICE_PLAN)
    @Retry(name = SERVICE_PLAN)
    public String listServicePlans(Model model) {
        List<serviceplandto> servicePlans = planService.getServicePlans();
        model.addAttribute("servicePlans", servicePlans);
        return "pages/plans/list";
    }

实现断路器模式

使用断路器模式来处理非暂时性故障的服务中断。 断路器模式可防止应用程序持续尝试访问无响应服务。 它会释放应用程序并避免浪费 CPU 周期,以便应用程序为最终用户保留其性能完整性。

使用 Spring 断路器Resilience4j 文档实现断路器模式。 例如,参考实现通过使用断路器属性修饰方法来实现断路器模式。

实现缓存端模式

缓存端模式添加到 Web 应用中,以改进内存中的数据管理。 该模式为应用程序分配处理数据请求的责任,并确保缓存与持久性存储(例如数据库)之间的一致性。 它缩短了响应时间,提高了吞吐量,并减少了对更多缩放的需求。 它还减少了主数据存储的负载,改善了可靠性和成本优化。 要实现缓存端模式,请遵循以下建议:

  • 将应用程序配置为使用缓存。 若要启用缓存,请将 spring-boot-starter-cache 包作为依赖项添加到 pom.xml 文件中。 此包提供 Redis 缓存的默认配置。

  • 缓存高需求数据。 在高需求数据上应用缓存端模式,以提高其有效性。 使用 Azure Monitor 跟踪数据库的 CPU、内存和存储。 这些指标有助于确定在应用“缓存端”模式后,是否可以使用更小的数据库 SKU。 要在代码中缓存特定数据,请添加 @Cacheable 批注。 此批注会告诉 Spring 哪些方法应缓存其结果。

  • 使缓存数据保持最新。 计划定期缓存更新,以便与最新的数据库更改保持同步。 根据数据波动性和用户需求确定最佳刷新率。 这种做法可确保应用程序使用缓存端模式提供快速访问和最新信息。 默认缓存设置可能不适合你的 Web 应用程序。 可以在 application.properties 文件或环境变量中自定义这些设置。 例如,可以修改 spring.cache.redis.time-to-live 值(以毫秒为单位),以控制数据在缓存中保留多长时间后才会被驱逐。

  • 确保数据一致性。 实施各种机制以在任何数据库写入操作后立即更新缓存。 使用事件驱动的更新或专用数据管理类来确保缓存一致性。 始终将缓存与数据库修改保持同步是缓存端模式的核心。

配置指南

以下各部分将为实现配置更新提供指导。 每个部分都与“架构良好的框架”的一个或多个支柱相一致。

配置 可靠性 (RE) 安全性 (SE) 成本优化 (CO) 卓越运营 (OE) 性能效率 (PE) 支持 WAF 原则
配置用户身份验证和授权 SE:05
OE:10
实现托管标识 SE:05
OE:10
适当规模的环境 CO:05
CO:06
实现自动缩减 RE:06
CO:12
PE:05
自动执行资源部署 OE:05
实现监视 OE:07
PE:04

配置用户身份验证和授权

在将 Web 应用程序迁移到 Azure 时,请配置用户身份验证和授权机制。 遵循以下建议:

  • 使用标识平台。 使用 Microsoft标识平台设置 Web 应用身份验证。 此平台支持使用单个 Microsoft Entra 目录、来自不同组织的多个 Microsoft Entra 目录以及Microsoft标识或社交帐户的应用程序。

    适用于 Microsoft Entra ID 的 Spring Boot Starter 可简化此过程,从而利用 Spring Security 和 Spring Boot 轻松设置。 它提供各种身份验证流、自动令牌管理和可自定义的授权策略,以及与 Spring Cloud 组件的集成功能。 这样就可以直接将 Microsoft Entra ID 和 OAuth 2.0 集成到 Spring Boot 应用程序中,而无需手动进行库或设置配置。

    例如,参考实现使用 Microsoft 标识平台(Microsoft Entra ID)作为 Web 应用的标识提供者。 它使用 OAuth 2.0 授权码授予以 Microsoft Entra 帐户登录用户。 以下 XML 代码段规定了 OAuth 2.0 认证码授权流的两个必需依赖项。 依赖项 com.azure.spring: spring-cloud-azure-starter-active-directory 在 Spring Boot 应用程序中启用 Microsoft Entra 身份验证和授权。 依赖项 org.springframework.boot: spring-boot-starter-oauth2-client 支持 Spring Boot 应用程序中的 OAuth 2.0 身份验证和授权。

    <dependency>
        <groupid>com.azure.spring</groupid>
        <artifactid>spring-cloud-azure-starter-active-directory</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-oauth2-client</artifactid>
    </dependency>
    
  • 创建应用注册。 Microsoft Entra ID 需要在主租户中注册应用程序。 应用程序注册可确保有权访问 Web 应用的用户在主租户中具有标识。 例如,参考实现使用 Terraform 创建 Microsoft Entra ID 应用注册和特定于应用的帐户管理器角色。

    resource "azuread_application" "app_registration" {
      display_name     = "${azurecaf_name.app_service.result}-app"
      owners           = [data.azuread_client_config.current.object_id]
      sign_in_audience = "AzureADMyOrg"  # single tenant
    
      app_role {
        allowed_member_types = ["User"]
        description          = "Account Managers"
        display_name         = "Account Manager"
        enabled              = true
        id                   = random_uuid.account_manager_role_id.result
        value                = "AccountManager"
      }
    }
    
  • 在应用程序中强制实现授权。 使用基于角色的访问控制 (RBAC),为应用程序角色分配最少的权限。 为不同的用户操作定义特定的角色,以避免重叠并确保清晰明了。 将用户映射到适当的角色,确保他们只能访问必要的资源和操作。 将 Spring Security 配置为使用适用于 Microsoft Entra ID 的 Spring Boot 启动器。 此库允许与 Microsoft Entra ID 集成,并协助对用户进行安全的身份验证。 通过配置和启用 Microsoft 身份验证库 (MSAL) ,可以访问更多安全功能。 这些功能包括令牌缓存和自动刷新令牌。

    例如,参考实现创建反映 Contoso Fiber 帐户管理系统中用户角色类型的应用角色。 在授权过程中,角色转换成权限。 CAMS 中特定于应用的角色的示例包括客户经理、一级 (L1) 支持代表和现场服务代表。 客户经理角色有权添加新的应用用户和客户。 现场服务代表可以创建支持票证。 PreAuthorize 属性限制对特定角色的访问。

        @GetMapping("/new")
        @PreAuthorize("hasAnyAuthority('APPROLE_AccountManager')")
        public String newAccount(Model model) {
            if (model.getAttribute("account") == null) {
                List<ServicePlan> servicePlans = accountService.findAllServicePlans();
                ServicePlan defaultServicePlan = servicePlans.stream().filter(sp -> sp.getIsDefault() == true).findFirst().orElse(null);
                NewAccountRequest accountFormData = new NewAccountRequest();
                accountFormData.setSelectedServicePlanId(defaultServicePlan.getId());
                model.addAttribute("account", accountFormData);
                model.addAttribute("servicePlans", servicePlans);
            }
            model.addAttribute("servicePlans", accountService.findAllServicePlans());
            return "pages/account/new";
        }
        ...
    

    为了与 Microsoft Entra ID 集成,参考实现使用 OAuth 2.0 授权代码授予流。 此流允许用户使用 Microsoft 帐户登录。 以下代码段介绍如何配置 SecurityFilterChain 以使用 Microsoft Entra ID 进行身份验证和授权。

    @Configuration(proxyBeanMethods = false)
    @EnableWebSecurity
    @EnableMethodSecurity
    public class AadOAuth2LoginSecurityConfig {
        @Bean
        SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.apply(AadWebApplicationHttpSecurityConfigurer.aadWebApplication())
                .and()
                    .authorizeHttpRequests()
                .requestMatchers(EndpointRequest.to("health")).permitAll()
                .anyRequest().authenticated()
                .and()
                    .logout(logout -> logout
                                .deleteCookies("JSESSIONID", "XSRF-TOKEN")
                                .clearAuthentication(true)
                                .invalidateHttpSession(true));
            return http.build();
        }
    }
    ...
    
  • 更倾向于临时访问仓库。 使用临时权限来防止未经授权的访问和违规行为,如共享访问签名 (SAS)。 使用用户委派 SAS 在授予临时访问权限时最大程度地提高安全性。 它是唯一使用 Microsoft Entra ID 凭据的 SAS,而无需永久存储帐户密钥。

  • 在 Azure 中强制实现授权。 使用 Azure RBAC 为用户标识分配最低权限。 Azure RBAC 决定标识可以访问哪些 Azure 资源、可以对这些资源做什么以及可以访问哪些区域。

  • 避免永久提升权限。 使用 Microsoft Entra Privileged Identity Management 为特权操作授予即时访问权限。 例如,开发人员通常需要管理员级别的访问权限来创建/删除数据库、修改表架构和更改用户权限。 通过即时访问,用户标识可获得执行特权任务的临时权限。

实现托管标识

对支持托管标识的所有 Azure 服务使用托管标识。 托管身份允许 Azure 资源(工作负荷标识)验证其他 Azure 服务并与之交互,而无需管理凭据。 混合系统和旧式系统可以保留本地身份验证解决方案,以简化迁移,但应尽快过渡到托管标识。 要实现托管标识,请遵循以下建议:

  • 选取正确的托管标识类型。 如果有两个或更多 Azure 资源需要同一组权限,请优先使用用户分配的托管标识。 此设置比为每个资源创建系统分配的托管标识并为所有资源分配相同的权限更为有效。 否则,请使用系统分配的托管标识。

  • 配置最低权限。 使用 Azure RBAC 仅授予对操作至关重要的权限,例如数据库中的 CRUD 操作或访问机密。 工作负荷标识具有永久权限,因此无法为工作负荷标识提供实时或短期权限。 如果 Azure RBAC 未涵盖特定方案,则可使用 Azure 服务级别访问策略对 Azure RBAC 进行补充。

  • 保护其余机密。 将其余机密存储在 Azure 密钥保管库中。 在应用程序启动时(而不是在每个 HTTP 请求期间)从密钥保管库加载机密。 HTTP 请求中的高频访问可能会超过密钥保管库事务限制。 将应用程序配置存储在 Azure 应用配置中。

适当规模的环境

使用能满足每个环境需求的 Azure 服务性能层 (SKU),而无需过多的数量。 要合理调整环境规模,请遵循以下建议:

  • 估算成本。 可使用 Azure 定价计算器估算每个环境的成本。

  • 优化生产环境的成本。 生产环境需要满足生产所需的服务级别协议 (SLA)、功能和规模的 SKU。 持续监控资源使用情况,并根据实际性能需求调整 SKU。

  • 优化预生产环境的成本。 预生产环境应使用成本较低的资源,禁用不需要的服务,并应用 Azure 开发/测试定价等折扣。 确保预生产环境与生产环境完全类似,以避免引入风险。 这种平衡既能确保测试的有效性,又不会产生不必要的费用。

  • 使用基础结构即代码 (IaC) 来定义 SKU。 实现 IaC,以便根据环境动态选择和部署正确的 SKU。 此方法可增强一致性,同时简化管理。

例如,参考实现具有部署其他 SKU 的可选参数。 环境参数指示 Terraform 模板选择开发 SKU。

azd env set APP_ENVIRONMENT prod

实现自动缩减

自动缩放可确保 Web 应用保持弹性、响应迅速,并能高效处理动态工作负荷。 要实现自动缩放,请遵循以下建议:

  • 自动横向扩展。使用 Azure 自动缩放在生产环境中自动进行水平缩放。 配置自动缩放规则,根据关键性能指标进行横向扩展,让应用程序能够处理不同的负荷。

  • 优化缩放触发器。 如果不熟悉应用程序的缩放要求,请首先将 CPU 利用率作为初始缩放触发器。 优化缩放触发器,使其包括 RAM、网络吞吐量和磁盘 I/O 等其他指标。 目的是匹配 Web 应用程序的行为,以提高性能。

  • 提供横向扩展缓冲区。 设置缩放阈值,以便在达到最大容量前触发。 例如,配置在 CPU 使用率达到 85% 时进行缩放,而不是等到 CPU 使用率达到 100%。 这种积极主动的方法有助于保持性能和避免潜在的瓶颈。

自动执行资源部署

使用自动化在所有环境中部署和更新 Azure 资源和代码。 遵循以下建议:

  • 使用基础结构即代码。 通过持续集成和持续交付 (CI/CD) 管道来部署基础结构即代码。 Azure 为每个 Azure 资源预制了 Bicep、ARM (JSON) 和 Terraform 模板

  • 使用持续集成/持续部署 (CI/CD) 管道。 使用 CI/CD 管道将代码从源代码控制部署到各种环境,如测试、暂存和生产环境。 如果使用的是适用于 GitHub 项目的 Azure DevOps 或 GitHub Actions,则使用 Azure Pipelines。

  • 集成单元测试 在部署到应用程序服务之前,在管道中设置所有单元测试的执行和传递优先级。 合并代码质量和覆盖率工具(如 SonarQube)以实现全面的测试覆盖率。

  • 采用模拟框架。 对于涉及外部终结点的测试,请使用模拟框架。 这些框架可创建模拟终结点。 它们消除了配置真实外部终结点的需要,并可确保跨环境的统一测试条件。

  • 执行安全扫描。 使用静态应用程序安全测试 (SAST) 在源代码中查找安全漏洞和编码错误。 此外,执行软件组合分析 (SCA),检查第三方库和组件是否存在安全风险。 执行这些分析的工具可以轻松集成到 GitHub 和 Azure DevOps 中。

配置监视

实现应用程序和平台监控,从而提高 Web 应用的卓越运行和性能效率。 要实现监控,请遵循以下建议:

  • 收集应用程序遥测。 使用 Azure Application Insights 中的 autoinstrumentation 来收集应用程序遥测数据(如请求吞吐量、平均请求持续时间、错误和依赖性监控),而无需更改代码。 Spring Boot 在 Application Insights 上显示多个核心指标,例如 Java 虚拟机 (JVM) 、CPU、Tomcat 等。 Application Insights 会自动从 Log4j 和 Logback 等日志记录框架上进行收集。 例如,参考实现将通过 Terraform 启用的 Application Insights 作为应用程序服务 app_settings 配置的一部分。 (请参阅以下代码)。

    app_settings = {
        APPLICATIONINSIGHTS_CONNECTION_STRING = var.app_insights_connection_string
        ApplicationInsightsAgent_EXTENSION_VERSION = "~3"
        ...
    }
    

    有关详细信息,请参阅:

  • 创建自定义应用程序指标。 通过添加 Application Insights SDK 并使用其 API 来实现基于代码的检测,以捕获自定义应用程序遥测

  • 监控平台。 为所有支持的服务启用诊断程序,并将诊断程序发送到与应用程序日志相同的目标,以便进行关联。 Azure 服务会自动创建平台日志,但只有在启用诊断功能时才会存储这些日志。 为每个支持诊断的服务启用诊断设置。 参考实现使用 Terraform 在所有受支持的服务上启用 Azure 诊断。 以下 Terraform 代码配置应用程序服务的诊断设置。

    # Configure Diagnostic Settings for App Service
    resource "azurerm_monitor_diagnostic_setting" "app_service_diagnostic" {
      name                           = "app-service-diagnostic-settings"
      target_resource_id             = azurerm_linux_web_app.application.id
      log_analytics_workspace_id     = var.log_analytics_workspace_id
      #log_analytics_destination_type = "AzureDiagnostics"
    
      enabled_log {
        category_group = "allLogs"
    
      }
    
      metric {
        category = "AllMetrics"
        enabled  = true
      }
    }
    

部署参考实现

参考实现指导开发人员完成从本地 Java 应用程序到 Azure 的模拟迁移,并强调了在最初采用阶段的必要更改。 本示例使用的是虚构公司 Contoso Fiber 的客户帐户管理系统 (CAMS) Web 应用程序。 Contoso Fiber 为其 Web 应用程序设定了以下目标:

  • 实现低成本、高价值的代码更改
  • 达到 99.9% 的服务级别目标 (SLO)
  • 采用 DevOps 做法
  • 创建成本优化的环境
  • 增强可靠性和安全性

Contoso Fiber 认为,要实现这些目标,他们的内部基础结构并非具有成本效益的解决方案。 他们决定将 CAMS Web 应用程序迁移到 Azure,认为这才是实现当下和未来目标最经济高效的方法。 以下体系结构代表了 Contoso Fiber 的可靠 Web 应用模式实现的最终状态。

显示了参考实现的体系结构的示意图。图 4. 参考实现的体系结构。下载此体系结构的 Visio 文件