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

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

Azure 应用程序服务
Azure Front Door

本文提供有关实现 Reliable Web App 模式的指导。 此模式描述如何修改用于云迁移的 Web 应用( replatform) Web 应用。 它提供与 azure Well-Architected Framework 原则一致的规范体系结构、代码和配置指南。

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

Reliable Web App 模式是一组原则和实现技术,用于定义在将 Web 应用迁移到云时应如何重新构建 Web 应用。 它重点介绍在云中取得成功所需的最少代码更新。 以下指南在整个过程中使用参考实现作为示例。 它遵循虚构公司 Contoso Fiber 的重新制定旅程,为旅程提供业务上下文。 在实现适用于 Java 的 Reliable Web App 模式之前,Contoso Fiber 具有使用 Spring Boot 框架的单体本地客户帐户管理系统(CAMS)。

提示

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

如何实现可靠 Web 应用模式

本文包括用于实现 Reliable Web App 模式的体系结构、代码和配置指南。 使用以下链接转到所需的特定指南:

  • 业务上下文。 将此指南与业务上下文保持一致,并了解如何定义推动重新制定决策的即时和长期目标。
  • 体系结构指南。 了解如何选择正确的云服务并设计符合业务需求的体系结构。
  • 代码指南。 实施三种设计模式,以提高云中 Web 应用的可靠性和性能效率:重试、断路器和 Cache-Aside 模式。
  • 配置指南。 配置身份验证和授权、托管标识、权限化环境、基础结构即代码和监视。

▪ 业务上下文

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

例如,Contoso Fiber 希望扩展其本地 CAMS Web 应用以访问其他区域。 为了满足 Web 应用日益增长的需求,他们制定了以下目标:

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

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

体系结构指南

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

显示 Reliable Web App 模式的基本体系结构元素的关系图。

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

设计体系结构

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

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

    对于多区域 Web 应用,请将负载均衡器配置为将流量路由到第二个区域,以支持主动-主动或主动-被动配置,具体取决于业务需求。 这两个区域需要相同的服务,但一个区域有一个连接区域的中心虚拟网络。 采用中心辐射型网络拓扑来集中和共享资源,如网络防火墙。 如果有虚拟机,请将堡垒主机添加到中心虚拟网络,以增强安全性来管理它们。 (见图2.

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

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

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

挑选正确的 Azure 服务

将 Web 应用移动到云时,应选择满足业务需求的 Azure 服务,并符合本地 Web 应用的功能。 这种对齐方式有助于最大程度地减少重新调整工作。 例如,使用可以保持相同数据库引擎并支持现有中间件和框架的服务。 以下各部分提供了为 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 容器应用? 以及 Azure 容器应用概述上的 Java
    • 高 SLA。 应用服务提供满足生产环境要求的高 SLA。
    • 减少了管理开销。 应用服务是一个完全托管的托管解决方案。
    • 容器化功能。 应用服务适用于专用容器映像注册表,例如 Azure 容器注册表。 Contoso Fiber 将来可以使用这些注册表对 Web 应用进行容器化。
    • 自动缩放。 Web 应用可以根据用户流量快速纵向扩展、缩减和缩小。
  • 标识管理:使用 Microsoft Entra ID 作为标识和访问管理解决方案。 Contoso Fiber 选择 Microsoft Entra ID 的原因如下:

    • 身份验证和授权。 应用程序需要对呼叫中心员工进行身份验证和授权。
    • 可伸缩性。 Microsoft Entra ID 缩放以支持更大的方案。
    • 用户标识控件。 呼叫中心员工可以使用其现有的企业标识。
    • 授权协议支持。 Microsoft Entra ID 支持托管标识的 OAuth 2.0。
  • 数据库:使用可保持相同数据库引擎的服务。 使用 数据存储决策树 来指导选择。 Contoso Fiber 出于以下原因选择了 Azure Database for PostgreSQL 和灵活的服务器部署模型:

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

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

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

    • 全局负载均衡。 它是一个第 7 层负载均衡器,可以跨多个区域路由流量。
    • Web 应用程序防火墙。 它以本机方式与 Azure Web 应用程序防火墙集成。
    • 路由灵活性。 它允许应用程序团队配置入口需求,以支持应用程序中未来的更改。
    • 流量加速。 它使用任何广播到达最近的 Azure 状态点,并找到到 Web 应用的最快路由。
    • 自定义域。 它支持具有灵活域验证的自定义域名。
    • 健康检查。 应用程序需要智能运行状况探测监视。 Azure Front Door 会根据这些探测响应来确定用于路由客户端请求的最佳源。
    • 监视支持。 Azure Front Door 支持内置报表,其中包含适用于 Azure Front Door 和安全模式的一个全能仪表板。 可以配置与 Azure Monitor 集成的警报。 Azure Front Door 允许应用程序记录每个请求和运行状况探测失败。
    • 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 出于以下原因使用了密钥保管库:

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

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

代码指导

若要成功将 Web 应用移动到云,需要使用重试模式、断路器模式和 Cache-Aside 模式更新 Web 应用代码。

关系图,显示 Reliable Web App 模式中设计模式的角色。

图 3. 设计模式的角色。

每个设计模式提供与 Well-Architected 框架的一个或多个支柱保持一致的工作负载设计优势。 以下是应该实现的模式概览:

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

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

  3. Cache-Aside 模式。 Cache-Aside 模式按需将数据加载到数据存储中的缓存中。 在请求数据库时实现此模式。

设计模式 可靠性 (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 Cloud 断路器复原能力 4j 实现断路器模式。 参考实现通过使用断路器属性修饰方法来实现断路器模式。

实现缓存端模式

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

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

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

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

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

配置指南

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

配置 可靠性 (RE) 安全性 (SE) 成本优化 (CO) 卓越运营 (OE) 性能效率 (PE) 支持 WAF 原则
配置用户身份验证和授权 SE:05
OE:10
实现托管标识 SE:05
OE:10
Rightsize 环境 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 应用配置中。

Rightsize 环境

使用满足每个环境需求的 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 管道将代码从源代码控制部署到各种环境,如测试、暂存和生产环境。 如果使用的是 Azure DevOps,请使用 Azure Pipelines。 将 GitHub Actions 用于 GitHub 项目。

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

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

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

配置监视

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

  • 收集应用程序遥测。 使用 Azure Application Insights 中的 自动 收集应用程序 遥测,例如请求吞吐量、平均请求持续时间、错误和依赖项监视。 无需更改任何代码以使用此遥测数据。 Spring Boot 在 Application Insights 中注册多个核心指标,例如 Java 虚拟机(JVM)、CPU、Tomcat 等。 Application Insights 会自动从 Log4j 和 Logback 等日志记录框架收集。

    参考实现使用 Application Insights,在应用服务的 app_settings 配置中通过 Terraform 启用:

    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 应用程序设置了以下目标:

  • 实现低成本、高价值代码更改。
  • 实现 SLO 为 99.9%。
  • 采用 DevOps 做法。
  • 创建成本优化的环境。
  • 提高可靠性和安全性。

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

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