问题描述
在 Azure App Service 中启用 Automatic Scaling 后,当业务负载增加并触发横向扩展时,平台可能需要动态增加新的 App Service 实例。
对于生产环境,一个非常重要的问题是:
如何确保新扩展出来的实例已经完成应用启动、依赖初始化并处于健康状态后,再开始承载实际业务流量,从而降低扩容过程对业务稳定性的影响?
解决这个问题不能只关注扩容规则本身,还需要从应用架构、应用初始化、实例健康检查以及预热能力几个方面共同考虑。
问题解答
在应用架构方面,需要确保应用采用对的是无状态设计(Stateless架构,应用处理每一个请求都是相互独立的,在Host实例(VM)上不依赖它的内存数据)。
根据App Service的官方文档说明:启用 Automatic Scaling 后,ARR Affinity 会自动关闭。
ARR Affinity 原本用于提供 Session Affinity,因此应用不应依赖客户端始终访问同一个 App Service 实例。因此,对于需要保存 Session、用户状态或业务上下文的应用,更推荐将状态存储在实例之外,例如 Redis、数据库或其他共享存储中,而不是保存在单个 Web App 实例的本地内存中。
这样当 Automatic Scaling 增加或减少实例时,请求可以由不同实例处理,而不会因为实例切换导致业务状态丢失。
而在剩下的三个方面:应用初始化(Application Initialization)、实例健康检查(Health Check)以及预热能力(Prewarmed Instance),他们分别解决什么问题呢?
简而言之:
- Application Initialization 提前初始化应用,完成应用预热。
- Health Check 检查健康,验证新实例健康状态。
- Prewarmed Instance 提供扩容缓冲,提前准备额外的计算实例。
本文将重点介绍 Application Initialization 应用初始化。
应用初始化(Application Initialization)
新实例被创建并不意味着应用已经完全准备好处理生产请求。应用进程启动之后,可能仍需要执行一系列初始化操作,例如:
- 加载应用组件和配置
- 建立数据库或其他后端依赖
- 初始化缓存
- 加载运行时资源
- 完成应用自身的启动逻辑
因此,可以配置 Application Initialization,对应用执行预热,使应用启动过程中需要的组件和依赖提前完成初始化,预热的作用是提前触发这些操作。
Windows:通过 IIS 触发初始化
Windows IIS 可通过 applicationInitialization 指定初始化路径,应用应在该路径触发必要的初始化。
注意:只配置初始化路径并不等于验证了业务就绪,还应结合 Health Check,并在测试环境确认实际扩容时的流量行为。(Health Check 将在第二部分内容中介绍)
Linux:用启动探测判断就绪
在 Settings > Environment variables 设置 WEBSITE_WARMUP_PATH=/ready 和 WEBSITE_WARMUP_STATUSES=200。
应用应在初始化完成且关键依赖可用后返回 200,尚未就绪时返回 503。平台会重复探测路径。
参考资料
IIS Application Initialization : https://learn.microsoft.com/iis/configuration/system.webserver/applicationinitialization/
App Service 应用设置 : https://learn.microsoft.com/azure/app-service/reference-app-settings
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!