本文提供有关实现 Reliable Web App 模式的指导。 此模式描述如何修改用于云迁移的 Web 应用( replatform) Web 应用。 它提供与 azure Well-Architected Framework 原则一致的规范体系结构、代码和配置指南。
为什么采用 .NET 的可靠 Web 应用模式?
Reliable Web App 模式是一组原则和实现技术,用于定义在将 Web 应用迁移到云时应如何重新构建 Web 应用。 它重点关注在云中取得成功所需的最低限度代码更新。 以下指南在整个过程中使用参考实现作为示例。 本指南遵循虚构公司 Relecloud 的重新制定旅程,为旅程提供业务上下文。 在实现 .NET 的 Reliable Web App 模式之前,Relecloud 具有使用 ASP.NET 框架的单一本地票证 Web 应用。
提示
有一个可靠 Web 应用模式的参考实现(示例)。 它表示名为 Relecloud 的虚构公司 Reliable Web App 实现的结束状态。 它是一个生产级 Web 应用,具有本文讨论的所有代码、体系结构和配置更新。 部署并使用参考实现来指导你实现可靠 Web 应用模式。
如何实现可靠 Web 应用模式
本文包括用于实现 Reliable Web App 模式的体系结构、代码和配置指南。 使用以下链接转到所需的特定指南:
- 业务上下文。 将此指南与业务上下文保持一致,并了解如何定义推动重新制定决策的即时和长期目标。
- 体系结构指南。 了解如何选择正确的云服务并设计符合业务需求的体系结构。
- 代码指南。 实施三种设计模式,以提高云中 Web 应用的可靠性和性能效率:重试、断路器和 Cache-Aside 模式。
- 配置指南。 配置身份验证和授权、托管标识、权限化环境、基础结构即代码和监视。
▪ 业务上下文
Web 应用重新平台化的第一步是确定业务目标。 应立即设定目标,例如服务级别目标(SLO)和成本优化目标,以及 Web 应用程序的未来目标。 这些目标会影响对云服务和云中 Web 应用体系结构的选择。 为 Web 应用定义目标 SLO,例如 99.9% 的正常运行时间。 计算影响 Web 应用可用性的所有服务的复合 SLA。
例如,Relecloud 对销售预测持乐观态度,预计 Web 应用票证需求会增加。 为了满足这一需求,他们明确了 Web 应用程序的目标:
- 应用低成本、高价值代码更改。
- 达到 99.9%的 SLO。
- 采用 DevOps 做法。
- 创建成本优化的环境。
- 提高可靠性和安全性。
为了实现这些目标,Relecloud 的本地基础结构显然不是一款经济高效的解决方案。 他们决定将 Web 应用程序迁移到 Azure 是实现其即时和未来目标的最经济高效的方法。
体系结构指南
可靠 Web 应用模式有几个基本的体系结构要素。 需要 DNS 来管理终结点解析、用于阻止恶意 HTTP 流量的 Web 应用程序防火墙,以及用于路由并帮助保护入站用户请求的负载均衡器。 应用程序平台托管 Web 应用代码,并通过虚拟网络中的专用终结点调用所有后端服务。 应用程序性能监视工具捕获指标和日志,以帮助了解 Web 应用。
图 1. 可靠 Web 应用模式的基本体系结构要素。
设计体系结构
设计基础结构以支持 恢复指标,例如恢复时间目标(RTO)和恢复点目标(RPO)。 RTO 会影响可用性,并且必须支持你的 SLO。 确定 RPO 并配置 数据冗余 以满足 RPO。
选择基础设施的可靠性。 确定满足可用性要求所需的可用性区域和区域数。 添加可用性区域和区域,直到复合 SLA 符合你的 SLO。 可靠 Web 应用模式支持多个区域,以实现主动-主动或主动-被动配置。 例如,参考实现采用主动-被动配置,以满足 99.9% 的 SLO 要求。
对于多区域 Web 应用,请将负载均衡器配置为将流量路由到第二个区域,以支持主动-主动或主动-被动配置,具体取决于业务需求。 这两个区域需要相同的服务,但一个区域有一个连接区域的中心虚拟网络。 采用中心辐射型网络拓扑来集中和共享资源,如网络防火墙。 如果有虚拟机,请将堡垒主机添加到中心虚拟网络,以增强安全性来管理它们。 (见图2.)
图 2. 可靠 Web 应用模式与第二个区域和中心辐射型拓扑。
选择网络拓扑。 根据 Web 和网络要求选择正确的网络拓扑。 如果计划使用多个虚拟网络,请使用 中心辐射型网络拓扑。 它为本地和虚拟网络提供成本、管理和安全优势和安全优势以及混合连接选项。
挑选正确的 Azure 服务
将 Web 应用移动到云时,应选择满足业务需求的 Azure 服务,并符合本地 Web 应用的当前功能。 这种对齐方式有助于最大程度地减少重新调整工作。 例如,使用可以保持相同数据库引擎并支持现有中间件和框架的服务。 以下各部分提供了为 Web 应用选择合适的 Azure 服务的指导。
例如,在迁移到云之前,Relecloud 的票证 Web 应用是本地整体 ASP.NET 应用。 它在两个虚拟机上运行,并使用 SQL Server 数据库。 Web 应用在可伸缩性和功能部署方面的常见问题。 基于这一出发点及其业务目标,SLO 推动他们做出了服务选择。
应用程序平台:使用 Azure 应用程序服务作为应用程序平台。 出于以下原因,Relecloud 选择应用服务作为应用程序平台:
- 高级服务级别协议(SLA)。 它具有高 SLA,满足生产环境 SLO 的 99.9%。
- 减少了管理开销。 它是一个完全托管的解决方案,用于处理缩放、运行状况检查和负载均衡。
- .NET 支持。 它支持应用程序写入的 .NET 版本。
- 容器化功能。 Web 应用可以在云上聚合,无需容器化,但应用程序平台也支持容器化,而无需更改 Azure 服务。
- 自动缩放。 Web 应用可以根据用户流量和配置设置自动横向扩展。 该平台还支持扩大或缩小规模,以适应不同的托管要求。
标识管理:使用 Microsoft Entra ID 作为标识和访问管理解决方案。 Relecloud 出于以下原因选择了Microsoft Entra ID:
- 身份验证和授权。 应用程序需要对呼叫中心员工进行身份验证和授权。
- 可 伸缩。 Microsoft Entra ID 缩放以支持更大的方案。
- 用户标识控件。 呼叫中心员工可以使用其现有的企业标识。
- 授权协议支持。 Microsoft Entra ID 支持托管标识的 OAuth 2.0。
数据库:使用可保持相同数据库引擎的服务。 使用 数据存储决策树 来指导选择。 Relecloud 的 Web 应用使用本地的 SQL Server。 他们希望使用现有的数据库架构、存储过程和函数。 Azure 上提供了多个 SQL 产品,但 Relecloud 出于以下原因选择了 Azure SQL Database:
- 可靠性。 常规用途层提供高 SLA 和多区域冗余。 它可以支持高用户负载。
- 减少了管理开销。 SQL 数据库提供托管 SQL 数据库实例。
- 迁移支持。 它支持从本地 SQL Server 迁移数据库。
- 与本地配置的一致性。 它支持现有的存储过程、函数和视图。
- 弹性。 它支持备份和时间点还原。
- 专业知识和最少的返工。 SQL 数据库使 Relecloud 能够利用现有专业知识,并且需要最少的工作才能采用。
应用程序性能监视: 使用 Application Insights 分析应用程序的遥测数据。 Relecloud 出于以下原因选择使用 Application Insights:
- 与 Azure Monitor 集成。 它提供与 Azure Monitor 的最佳集成。
- 异常情况检测。 它会自动检测性能异常。
- 故障 排除。 它可帮助你诊断正在运行的应用中的问题。
- 监测。 它收集有关用户如何使用应用的信息,并使你能够轻松跟踪自定义事件。
- 可见性差距。 本地解决方案没有应用程序性能监视解决方案。 Application Insights 提供与应用程序平台和代码的轻松集成。
缓存: 选择是否向 Web 应用体系结构添加缓存。 Azure Redis 缓存 是主要的 Azure 缓存解决方案。 它是基于 Redis 软件的托管内存中数据存储。 Relecloud 的 Web 应用负载严重偏向于观看音乐会和场地详细信息。 Relecloud 添加了 Azure Redis 缓存,原因如下:
- 减少了管理开销。 它是一项完全托管的服务。
- 速度和音量。 对于经常访问、变化缓慢的数据,它具有高数据吞吐量和低延迟读取。
- 不同的可支持性。 它是 Web 应用的所有实例要使用的统一缓存位置。
- 外部数据存储。 本地应用程序服务器执行 VM 本地缓存。 此设置未卸载频繁使用的数据,并且无法使数据失效。
- 非粘性会话。 外部化会话状态支持非粘性会话。
负载均衡器: 使用 PaaS 解决方案的 Web 应用程序应使用 Azure Front Door、Azure 应用程序网关或两者,具体取决于 Web 应用体系结构和要求。 使用负载均衡器决策树来选取正确的负载均衡器。 Relecloud 需要一个 7 层负载均衡器,该负载均衡器可以跨多个区域路由流量。 该公司需要一个多区域 Web 应用来满足 SLO 的 99.9%。 Relecloud 出于以下原因选择了 Azure Front Door:
- 全局负载均衡。 它是一个第 7 层负载均衡器,可以跨多个区域路由流量。
- Web 应用程序防火墙。 它以本机方式与 Azure Web 应用程序防火墙集成。
- 路由灵活性。 它允许应用程序团队配置入口需求,以支持应用程序中未来的更改。
- 流量加速。 它使用任何广播到达最近的 Azure 状态点,并找到到 Web 应用的最快路由。
- 自定义域。 它支持具有灵活域验证的自定义域名。
- 运行状况探测。 应用程序需要智能运行状况探测监视。 Azure Front Door 会根据这些探测响应来确定用于路由客户端请求的最佳源。
- 监视支持。 它支持内置报表,其中包含一个适用于 Azure Front Door 和安全模式的一个仪表板。 可以配置与 Azure Monitor 集成的警报。 Azure Front Door 使应用程序能够记录每个请求和运行状况探测失败。
- DDoS 防护。 它具有内置的第 3-4 层 DDoS 保护。
- 内容分发网络。 它将 Relecloud 定位为使用内容分发网络。 内容分发网络提供站点加速。
Web 应用程序防火墙:使用Azure Web 应用程序防火墙提供集中防护,防止常见的网络攻击和漏洞。 Relecloud 出于以下原因使用 Azure Web 应用程序防火墙:
- 全局保护。 它提供改进的全球 Web 应用保护,而不会牺牲性能。
- 僵尸网络保护。 团队可以监视和配置设置,以解决与僵尸网络相关的安全问题。
- 与本地奇偶校验。 本地解决方案在 IT 管理的 Web 应用程序防火墙后面运行。
- 易于使用。 Web 应用程序防火墙与 Azure Front Door 集成。
配置存储:选择是否将应用配置存储添加到 Web 应用。 Azure 应用程序配置是一种服务,用于集中管理应用程序设置和功能标志。 查看应用程序配置最佳做法,以确定此服务是否适合你的应用。 Relecloud 希望将基于文件的配置替换为与应用程序平台和代码集成的中央配置存储。 他们出于以下原因向体系结构添加了应用配置:
- 灵活性。 它支持功能标志。 功能标志允许用户在生产环境中选择加入和退出早期预览功能,而无需重新部署应用。
- Git 管道支持。 配置数据的事实来源必须是 Git 存储库。 更新中央配置存储中的数据所需的管道。
- 托管标识支持。 它支持托管标识,以简化并帮助保护与配置存储的连接。
机密管理器:如果要在 Azure 中管理机密,请使用 Azure Key Vault。 可以使用 ConfigurationBuilder 对象在 .NET 应用中合并 Key Vault。 Relecloud 的本地 Web 应用将机密存储在代码配置文件中,但更好的安全做法是将机密存储在支持 RBAC 和审核控制的位置。 尽管 托管标识 是连接到 Azure 资源的首选解决方案,但 Relecloud 具有管理所需的应用程序机密。 Relecloud 出于以下原因使用了密钥保管库:
- 加密。 它支持静态加密和传输中加密。
- 托管标识支持。 应用程序服务可以使用托管标识访问机密存储。
- 监视和日志记录。 Key Vault 有助于审核访问,并在存储的机密更改时生成警报。
- 集成。 Key Vault 提供与 Azure 配置存储(应用配置)和 Web 托管平台(应用服务)的本机集成。
存储解决方案: 请参阅 Azure 存储选项 根据要求选择正确的存储解决方案。 在本地,Relecloud 的 Web 应用已将磁盘存储装载到每个 Web 服务器上,但是团队希望使用外部数据存储解决方案。 Relecloud 出于以下原因选择了 Azure Blob 存储:
- 增强的安全性访问。 Web 应用可以消除通过匿名访问访问公开给公共 Internet 的存储的终结点。
- 加密。 Blob 存储对静态和传输中的数据进行加密。
- 弹性。 Blob 存储支持区域冗余存储(ZRS)。 区域冗余存储跨主要区域中的三个 Azure 可用性区域同步复制数据。 每个可用性区域都是一个独立的物理位置,具有独立的电源、冷却系统和网络。 此配置应使票证图像具备丢失复原能力。
终结点安全性: 使用 Azure 专用链接 通过虚拟网络中的专用终结点访问平台即服务(PaaS)解决方案。 虚拟网络与服务之间的流量将遍历 Microsoft 主干网络。 Relecloud 出于以下原因选择了专用链接:
- 增强的安全性通信。 专用链接允许应用程序在 Azure 平台上私下访问服务,并减少数据存储的网络占用,以帮助防止数据泄露。
- 工作量最少。 专用终结点支持 Web 应用平台和 Web 应用使用的数据库平台。 这两个平台都镜像了现有的本地配置,因此需要最少的更改。
网络安全。 使用 Azure 防火墙 来控制网络级别的入站和出站流量。 使用 Azure Bastion 连接到具有增强安全性的虚拟机,而无需公开 RDP/SSH 端口。 Relecloud 采用中心辐射型网络拓扑,并希望将共享网络安全服务置于中心内。 Azure 防火墙通过检查支路的所有出站流量来提高网络安全,从而提高安全性。 Relecloud 需要 Azure Bastion 才能从 DevOps 子网中的跳转主机进行增强安全性部署。
代码指导
若要成功将 Web 应用移动到云,需要使用重试模式、断路器模式和 Cache-Aside 模式更新 Web 应用代码。
图 3. 设计模式的角色。
每个设计模式提供与 Well-Architected 框架的一个或多个支柱保持一致的工作负载设计优势。 以下是应该实现的模式概览:
重试模式。 重试模式通过重试间歇性失败的作来处理暂时性故障。 在对其他 Azure 服务的所有向外呼叫中实现此模式。
断路器模式。 断路器模式可防止应用程序重试非暂时性作。 在对其他 Azure 服务的所有向外调用中执行此模式。
Cache-Aside 模式。 Cache-Aside 模式按需将数据加载到数据存储中的缓存中。 在请求数据库时实现此模式。
设计模式 | 可靠性 (RE) | 安全性 (SE) | 成本优化 (CO) | 卓越运营 (OE) | 性能效率 (PE) | 支持 WAF 原则 |
---|---|---|---|---|---|---|
重试模式 | ✔ | RE:07 | ||||
断路器模式 | ✔ | ✔ |
RE:03 RE:07 PE:07 PE:11 |
|||
Cache-Aside 模式 | ✔ | ✔ |
RE:05 PE:08 PE:12 |
实现重试模式
在应用程序代码中添加重试模式,以解决临时服务中断问题。 这些中断被称为暂时性故障。 暂时性故障通常会在几秒钟内自行解决。 使用重试模式可以重新发送失败的请求。 它还使你能够配置重试和尝试在失败之前尝试次数之间的延迟。
使用内置重试机制。 使用大多数 Azure 服务提供的内置重试机制来加快实现速度。 例如,参考实现使用 Entity Framework Core 中的 连接复原能力将重试模式应用于 SQL 数据库:
services.AddDbContextPool<ConcertDataContext>(options => options.UseSqlServer(sqlDatabaseConnectionString, sqlServerOptionsAction: sqlOptions => { sqlOptions.EnableRetryOnFailure( maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(3), errorNumbersToAdd: null); }));
使用重试编程库。 对于 HTTP 通信,请集成标准复原库,例如 Polly 或
Microsoft.Extensions.Http.Resilience
。 这些库提供全面的重试机制,对于管理与外部 Web 服务的通信至关重要。 例如,每次代码构造调用IConcertSearchService
对象的对象时,引用实现都会使用 Polly 强制实施重试模式:private void AddConcertSearchService(IServiceCollection services) { var baseUri = Configuration["App:RelecloudApi:BaseUri"]; if (string.IsNullOrWhiteSpace(baseUri)) { services.AddScoped<IConcertSearchService, MockConcertSearchService>(); } else { services.AddHttpClient<IConcertSearchService, RelecloudApiConcertSearchService>(httpClient => { httpClient.BaseAddress = new Uri(baseUri); httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/json"); httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "Relecloud.Web"); }) .AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetCircuitBreakerPolicy()); } } private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() { var delay = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(500), retryCount: 3); return HttpPolicyExtensions .HandleTransientHttpError() .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .WaitAndRetryAsync(delay); }
实现断路器模式
使用断路器模式来处理非暂时性故障的服务中断。 断路器模式可防止应用程序持续尝试访问无响应服务。 它释放应用程序并有助于防止浪费 CPU 周期,以便应用程序保持其最终用户的性能完整性。
例如,参考实现会将断路器模式应用于对 API 的所有请求。 它使用 HandleTransientHttpError
逻辑来检测可以安全重试的 HTTP 请求,但会限制指定时间段内聚合故障的数量:
private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
实现缓存端模式
将缓存端模式添加到 Web 应用中,以改进内存中的数据管理。 该模式为应用程序分配了处理数据请求的责任,并确保缓存和持久性存储(例如数据库)之间的一致性。 它缩短了响应时间,提高了吞吐量,并减少了对更多缩放的需求。 它还减少了主数据存储上的负载,从而提高可靠性和成本优化。 要实现缓存端模式,请遵循以下建议:
将应用程序配置为使用缓存。 生产应用应使用分布式 Redis 缓存。 此缓存通过减少数据库查询来提高性能。 它还启用非粘性会话,以便负载均衡器可以均匀分配流量。 引用实现使用分布式 Redis 缓存。
AddAzureCacheForRedis
方法 将应用程序配置为使用 Azure Redis 缓存:private void AddAzureCacheForRedis(IServiceCollection services) { if (!string.IsNullOrWhiteSpace(Configuration["App:RedisCache:ConnectionString"])) { services.AddStackExchangeRedisCache(options => { options.Configuration = Configuration["App:RedisCache:ConnectionString"]; }); } else { services.AddDistributedMemoryCache(); } }
缓存高需求数据。 对高需求数据应用 Cache-Aside 模式以提高其有效性。 使用 Azure Monitor 跟踪数据库的 CPU、内存和存储。 这些指标有助于确定应用 Cache-Aside 模式后是否可以使用较小的数据库 SKU。 例如,参考实现缓存了支持“音乐会预告”页面的高需求数据。
GetUpcomingConcertsAsync
方法将数据从 SQL 数据库拉取到 Redis 缓存中,并使用最新的音乐会数据填充缓存:public async Task<ICollection<Concert>> GetUpcomingConcertsAsync(int count) { IList<Concert>? concerts; var concertsJson = await this.cache.GetStringAsync(CacheKeys.UpcomingConcerts); if (concertsJson != null) { // There is cached data. Deserialize the JSON data. concerts = JsonSerializer.Deserialize<IList<Concert>>(concertsJson); } else { // There's nothing in the cache. Retrieve data // from the repository and cache it for one hour. concerts = await this.database.Concerts.AsNoTracking() .Where(c => c.StartTime > DateTimeOffset.UtcNow && c.IsVisible) .OrderBy(c => c.StartTime) .Take(count) .ToListAsync(); concertsJson = JsonSerializer.Serialize(concerts); var cacheOptions = new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) }; await this.cache.SetStringAsync(CacheKeys.UpcomingConcerts, concertsJson, cacheOptions); } return concerts ?? new List<Concert>(); }
使缓存数据保持最新。 计划定期缓存更新,以便与最新的数据库更改保持同步。 使用数据波动性和用户需要确定最佳刷新率。 这种做法可确保应用程序使用 Cache-Aside 模式提供快速访问和当前信息。 例如,引用实现仅在一小时内缓存数据,并在数据更改时使用
CreateConcertAsync
方法清除缓存键:public async Task<CreateResult> CreateConcertAsync(Concert newConcert) { database.Add(newConcert); await this.database.SaveChangesAsync(); this.cache.Remove(CacheKeys.UpcomingConcerts); return CreateResult.SuccessResult(newConcert.Id); }
确保数据一致性。 实施各种机制以在任何数据库写入操作后立即更新缓存。 使用事件驱动的更新或专用数据管理类来确保缓存一致性。 始终将缓存与数据库修改保持同步是缓存端模式的核心。 引用实现使用
UpdateConcertAsync
方法使缓存中的数据保持一致:public async Task<UpdateResult> UpdateConcertAsync(Concert existingConcert), { database.Update(existingConcert); await database.SaveChangesAsync(); this.cache.Remove(CacheKeys.UpcomingConcerts); return UpdateResult.SuccessResult(); }
配置指南
以下部分提供有关实现配置更新的指导。 每个部分都与“架构良好的框架”的一个或多个支柱相一致。
配置 | 可靠性 (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 需要在主租户中注册应用程序。 应用程序注册有助于确保有权访问 Web 应用的用户在主租户中具有标识。
使用平台功能。 通过使用平台功能来验证用户身份和访问数据,最大限度地减少对自定义验证代码的需求。 例如,应用服务 提供内置身份验证支持,因此你可以在 Web 应用中编写最少或无代码时登录用户和访问数据。
在应用程序中强制实现授权。 使用 RBAC 将最小特权分配给 应用程序角色。 为不同的用户操作定义特定的角色,以避免重叠并确保清晰明了。 将用户映射到相应的角色,并确保他们只能访问必要的资源和作。
更倾向于临时访问仓库。 使用临时权限来防范未经授权的访问和违规。 例如,可以使用 共享访问签名(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 应用配置中。
引用实现使用 SQL 数据库连接字符串中的 Authentication
参数,以便应用服务可以使用托管标识 Server=tcp:my-sql-server.database.windows.net,1433;Initial Catalog=my-sql-database;Authentication=Active Directory Default
连接到 SQL 数据库。 它使用 DefaultAzureCredential
允许 Web API 使用托管标识连接到 Key Vault:
builder.Configuration.AddAzureAppConfiguration(options =>
{
options
.Connect(new Uri(builder.Configuration["Api:AppConfig:Uri"]), new DefaultAzureCredential())
.ConfigureKeyVault(kv =>
{
// Some of the values coming from App Configuration
// are stored in Key Vault. Use the managed identity
// of this host for the authentication.
kv.SetCredential(new DefaultAzureCredential());
});
});
Rightsize 环境
使用满足每个环境需求的 Azure 服务的性能层(SKU),而无需超过它们。 若要对环境进行权限化,请遵循以下建议:
估算成本。 可使用 Azure 定价计算器估算每个环境的成本。
成本优化生产环境。 生产环境需要满足生产所需的服务级别协议 (SLA)、功能和规模的 SKU。 持续监控资源使用情况,并根据实际性能需求调整 SKU。
成本优化预生产环境。预生产环境 应使用低成本资源,并利用 Azure 开发/测试定价等折扣。 在这些环境中,应禁用不需要的服务。 同时,确保 预生产环境与生产 环境足够相似,以避免引入风险。 保持这种平衡可确保测试保持有效,而不会产生不必要的成本。
使用基础结构即代码(IaC)来定义 SKU。 实现 IaC,以便根据环境动态选择和部署正确的 SKU。 此方法可增强一致性,同时简化管理。
例如,参考实现使用 Bicep 参数将更昂贵的层(SKU)部署到生产环境:
var redisCacheSkuName = isProd ? 'Standard' : 'Basic'
var redisCacheFamilyName = isProd ? 'C' : 'C'
var redisCacheCapacity = isProd ? 1 : 0
实现自动缩减
自动缩放有助于确保 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 中的 自动 收集应用程序 遥测,例如请求吞吐量、平均请求持续时间、错误和依赖项监视。 无需进行任何代码更改才能使用此遥测数据。
引用实现使用 NuGet 包
Microsoft.ApplicationInsights.AspNetCore
中的AddApplicationInsightsTelemetry
来启用 遥测收集:public void ConfigureServices(IServiceCollection services) { ... services.AddApplicationInsightsTelemetry(Configuration["App:Api:ApplicationInsights:ConnectionString"]); ... }
创建自定义应用程序指标。 对自定义遥测使用基于代码的检测。 将 Application Insights SDK 添加到代码并使用 Application Insights API。
参考实现会收集 cart 活动相关事件的遥测数据。
this.telemetryClient.TrackEvent
计算添加到购物车中的票证。 它提供事件名称(AddToCart
),并指定具有concertId
和count
的字典:this.telemetryClient.TrackEvent("AddToCart", new Dictionary<string, string> { { "ConcertId", concertId.ToString() }, { "Count", count.ToString() } });
监控平台。 为所有受支持的服务启用诊断。 将诊断发送到与应用程序日志相同的目标,以便关联。 Azure 服务会自动创建平台日志,但仅在启用诊断时存储它们。 为每个支持诊断的服务启用诊断设置。
部署参考实现
参考实现指导开发人员完成从本地 ASP.NET 应用程序到 Azure 的模拟迁移,重点介绍了初始采用阶段所需的更改。 本示例使用了虚构公司 Relecloud 的音乐会票务应用程序,该公司通过内部 Web 应用程序来销售门票。 Relecloud 为其 Web 应用程序设定了以下目标:
- 实现低成本、高价值代码更改。
- 实现 SLO 为 99.9%。
- 采用 DevOps 做法。
- 创建成本优化的环境。
- 提高可靠性和安全性。
Relecloud 确定其本地基础结构不是满足这些目标的经济高效的解决方案。 他们决定将 Web 应用程序迁移到 Azure 是实现其即时和未来目标的最经济高效的方法。 以下体系结构表示 Relecloud 可靠 Web 应用模式实现的结束状态。