Microsoft 致力于确保 Azure 服务一直可用。 但是,可能会发生计划外服务中断。 当应用程序需要复原能力时,应为应用配置异地冗余。 此外,还应制定灾难恢复计划来处理区域性服务中断。 灾难恢复计划的一个重要部分是确保能够在主副本不可用时切换至应用程序和存储帐户的次要副本。
在 Durable Functions 中,所有状态默认保留在 Azure 存储中。 任务中心是用于业务流程和实体的 Azure 存储资源的逻辑容器。 业务流程协调程序、活动和实体函数只能在它们属于同一任务中心时相互交互。 本文档在描述保持这些 Azure 存储资源高度可用的方案时,会提到任务中心。
可以使用通过 HTTP 触发的 客户端函数 或其他受支持的 Azure Functions 触发器类型之一来触发业务流程和实体。 还可以使用 内置 HTTP API 触发它们。 为简单起见,本文重点介绍涉及 Azure 存储和基于 HTTP 的函数触发器的方案,以及用于提高可用性并在灾难恢复活动期间最大程度地减少停机时间的选项。 未显式涵盖其他触发器类型,例如服务总线或 Azure Cosmos DB 触发器。
本文中的方案基于主动-被动配置,最适合使用 Azure 存储。 此模式包括将备份(被动)函数应用部署到其他区域。 流量管理器监视主要(活动)函数应用以检测 HTTP 可用性。 当主应用程序失败时,它会切换到备用函数应用程序。 有关详细信息,请参阅 Azure 流量管理器的 优先级 Traffic-Routing 方法。
为 Durable Functions 配置主动-被动故障转移配置时,请记住以下注意事项:
- 本文中的指南假定你使用默认 的 Azure 存储提供程序 来存储 Durable Functions 运行时状态。 还可以配置备用存储提供程序,这些提供程序将状态存储在其他位置,例如在 SQL Server 数据库中。 备用存储提供程序可能需要不同的灾难恢复和异地分发策略。 有关备用存储提供程序的详细信息,请参阅 Durable Functions 存储提供程序 文档。
- 建议的主动-被动配置可确保客户端始终能够通过 HTTP 触发新业务流程。 但是,由于两个功能应用共享存储中的同一任务中心,导致一些后台存储事务在这两个应用之间进行分配。 由于此分布,此配置可能会导致次要函数应用的出口成本增加。
- 在主要区域中创建的基础存储帐户和任务中心由两个函数应用共享。
- 在通过 HTTP 激活的情况下,冗余部署的所有函数应用都必须共享相同的函数访问密钥。 Functions 运行时公开一个 管理 API ,使使用者能够以编程方式添加、删除和更新函数密钥。 还可以使用 Azure 资源管理器 API 管理密钥。
方案 1 - 使用共享存储进行负载均衡计算
为了减轻当函数应用资源不可用时发生停机时间的可能性,此方案使用部署到不同区域的两个函数应用。 流量管理器配置为检测主函数应用中的问题,并自动将流量重定向到次要区域中的函数应用。 此函数应用共享相同的 Azure 存储帐户和任务中心。 因此,函数应用的状态不会丢失,工作可以正常恢复。 将运行状况还原到主要区域后,Azure 流量管理器会自动将请求路由到该函数应用。
使用此部署方案时,有几个好处:
- 如果计算基础结构失败,可以在故障转移区域中恢复工作,而不会丢失数据。
- 自动流量管理器负责将负载自动切换至健康的函数应用。
- 流量管理器在故障解除后会自动恢复流量并将其重新定向到主应用功能。
但是,使用此方案需要考虑:
- 如果使用专用应用服务计划部署函数应用,则复制故障转移数据中心中的计算基础结构会增加成本。
- 此方案涵盖计算基础结构中断,但存储帐户仍然是函数应用的单一故障点。 如果发生存储中断,应用程序将停机。
- 如果 Function App 发生故障转移,则会增加延迟,因为它跨区域访问其存储帐户。
- 故障转移时,函数应用程序访问原始区域中的存储服务,这可能会导致网络出口流量产生更高的成本。
- 此方案取决于流量管理器,在客户端应用程序需要再次从流量管理器请求函数应用地址之前可能需要一些时间。 有关详细信息,请参阅 流量管理器的工作原理。
注释
从 Durable Functions 扩展版本 2.3.0 开始,可以使用同一存储帐户和任务中心配置安全地运行两个函数应用。 要启动的第一个应用将获取应用程序级 Blob 租约,该租约可防止其他应用从任务中心队列中窃取消息。 如果第一个应用停止运行,则其租约将过期,并可由第二个应用获取。 然后,第二个应用继续处理任务中心消息。
在 v2.3.0 之前,配置为使用同一存储帐户的函数应用会同时处理消息和更新存储项目,从而导致整体延迟增加以及传出成本升高。 如果主要应用和副本应用部署了不同的代码(即使是暂时的)则业务流程也可能无法正确执行,因为两个应用中的业务流程协调程序函数不一致。 因此,出于灾难恢复目的需要异地分发的所有应用都应使用 Durable 扩展的 v2.3.0 或更高版本。
方案 2 - 使用区域存储或区域持久任务计划程序进行负载均衡计算
上述方案仅涵盖仅限于计算基础结构的故障方案,建议使用故障转移解决方案。 当存储服务或持久任务计划程序(DTS)失败时,函数应用也会中断。
为了确保持久函数的持续作,此方案会在托管函数应用的每个区域中部署专用存储帐户或计划程序(DTS 实例)。 目前,使用 Durable Task Scheduler 时,建议使用灾难恢复方法。
此方法对前面的方案进行了改进:
- 区域状态隔离: 每个函数应用都链接到其自己的区域存储帐户或 DTS 实例。 如果函数应用失败,流量管理器会将流量重定向到次要区域。 由于每个区域中的函数应用程序使用其本地存储或分布式事务存储 (DTS),因此持久函数可以使用本地状态继续处理。
- 故障转移时未添加延迟: 在故障转移期间,函数应用和状态提供程序(存储或 DTS)会部署在一起,因此在故障转移区域不会产生额外的延迟。
- 对状态支持失败的复原能力: 如果一个区域中的存储帐户或 DTS 实例失败,该区域中的持久函数将失败,这会触发重定向到次要区域。 由于计算和应用状态都是隔离的,因此每个区域,故障转移区域的持久函数仍可正常运行。
此方案的重要注意事项:
- 如果使用专用应用服务计划部署函数应用,则复制故障转移数据中心中的计算基础结构会增加成本。
- 当前状态并未发生故障转移,这意味着在主区域恢复之前,现有的编排流程和实体对象将处于有效暂停状态并不可用。
总之,第一个和第二个场景之间的权衡是,延迟得以保持,出口成本得到最小化,但在停机期间,现有编排系统和实体不可用。 这些权衡是否可接受取决于应用程序的要求。
方案 3 - 使用 GRS 共享存储进行负载均衡计算
此方案是对第一种方案(实现共享存储帐户)的修改。 主要区别在于存储帐户是在启用异地复制的情况下创建的。 在功能上,此方案提供与方案 1 相同的优势,但它可实现其他数据恢复优势:
- 异地冗余存储(GRS)和可读访问异地冗余存储(RA-GRS)能够最大化提升存储帐户的可用性。
- 如果存储服务发生区域性中断,可以 手动启动到次要副本的故障转移。 在发生重大灾难导致区域丢失的极端情况下,Microsoft可能会启动区域故障转移。 在这种情况下,您无需执行任何操作。
- 发生故障转移时,持久函数的状态将保留到存储帐户的最后一次复制,这通常每隔几分钟发生一次。
与其他方案一样,有一些重要注意事项:
- 故障转移到副本可能需要一些时间。 在故障转移完成和 Azure 存储 DNS 记录更新之前,函数应用将继续不可访问。
- 使用异地复制的存储帐户会增加成本。
- GRS 复制以异步方式复制数据。 由于复制过程的延迟,某些最新事务可能会丢失。
注释
如方案 1 中所述,建议使用此策略部署的函数应用使用 Durable Functions 扩展的 v2.3.0 或更高版本。
有关详细信息,请参阅 Azure 存储灾难恢复和存储帐户故障转移 文档。