在 Azure Functions 中,单个函数应用实例允许并发处理多个事件。 由于这些实例在同一计算实例上运行,因此它们共享内存、CPU 和连接资源。 在某些托管计划中,对特定实例的高需求会导致 Functions 主机自动创建新实例来处理增加的负载。 在这些 动态规模 计划中,并发和扩展行为之间存在取舍。 为了更好地控制应用运行方式,Functions 提供了一种管理并发执行数的方法。
Functions 提供了两种主要方法来管理并发:
- 修复了每个实例的并发性:可以针对特定于单个触发器的并发配置主机级限制。 此模型是 Functions 的默认并发行为。
- 动态并发:对于某些触发器类型,Functions 主机可以自动确定函数应用中该触发器的最佳并发级别。 必须选择加入此并发模型。
本文介绍 Functions 中事件驱动触发器的并发行为,以及这些行为如何影响动态方案中的伸缩性。 它还比较了固定每个实例和动态并发模型。
扩展性与并发
对于使用基于事件的触发器或响应 HTTP 请求的函数,可以在高需求期间快速达到并发执行的限制。 在这些时间段内,必须能够通过添加实例来缩放函数应用,以避免处理传入请求的积压工作。 我们扩展应用程序的方式具体取决于你的托管计划:
缩放类型 | 托管计划 | 说明 |
---|---|---|
动态(事件驱动)缩放 |
消费 弹性消耗 高级 |
在动态扩展计划中,主机会根据传入事件的数量来增加或减少函数应用程序实例的数量。 有关详细信息,请参阅 Azure Functions 中的事件驱动缩放。 |
手动缩放 | 专用(应用服务)计划 | 在专用计划中托管函数应用时,必须在负载较高期间手动配置实例,或者设置自动缩放方案。 |
在发生任何缩放之前,函数应用会尝试通过在单个实例中处理同一类型的多个调用来应对负载的增加。 因此,给定实例上的这些并发执行直接影响缩放决策。 例如,当动态缩放计划中的应用达到并发限制时,可能需要进行缩放以满足传入的需求。
在应用中尝试实现的缩放与并发的平衡取决于可能出现瓶颈的位置:在处理(CPU 密集型进程限制)或下游服务(基于 I/O 的限制)中。
设置了每个实例的并发数上限
默认情况下,大多数触发器通过 基于目标的缩放支持固定的按实例并发配置模型。 在此模型中,每个触发器类型都有每实例并发限制。
可以通过为该触发器类型设置特定的实例并发度来覆盖大多数触发器的并发默认值。 对于许多触发器,可以在 host.json 文件中配置并发设置。 例如,Azure 服务总线触发器在 MaxConcurrentCalls
中提供 MaxConcurrentSessions
设置和 设置。 这些设置协同工作,控制每个函数应用在每个实例上并发处理的最大消息数。
在某些基于目标的缩放方案中,例如使用 Apache Kafka 或 Azure Cosmos DB 触发器时,并发配置位于函数声明中,而不是在 host.json 文件中。 其他触发器类型具有用于跨实例的负载均衡调用的内置机制。 例如,Azure 事件中心和 Azure Cosmos DB 都使用基于分区的方案。
对于支持并发配置的触发器类型,并发设置将应用于所有正在运行的实例。 这样,就可以控制每个实例上函数的最大并发性。 例如,当函数占用大量 CPU 或资源密集型时,可以选择限制并发以保持实例正常运行。 在这种情况下,可以依靠缩放来处理增加的负载。 同样,当函数向被限制的下游服务发出请求时,还应考虑限制并发以避免下游服务过载。
HTTP 触发器并发
仅适用于弹性消耗计划
HTTP 触发器并发是固定每个实例并发的特殊类型。 在 HTTP 触发器并发中,默认并发也取决于 实例内存大小。
Flex 消耗计划将所有 HTTP 触发器函数作为一个组一起进行缩放。 有关详细信息,请参阅按函数缩放。
下表根据配置的实例内存大小指示给定实例上 HTTP 触发器的默认并发设置:
实例大小 (MB) | 默认并发数* |
---|---|
512 | 4 |
2,048 | 16 |
4,096 | 32 |
*在 Python 应用中,所有实例大小默认使用一个 HTTP 触发器并发级别。
这些默认值适用于大多数情况,你可以从它们开始。 请注意,在 HTTP 请求数一定的情况下,增加 HTTP 并发值可减少处理 HTTP 请求所需的实例数。 同样,减少 HTTP 并发值需要更多实例来处理相同的负载。
如果需要微调 HTTP 并发,可以使用 Azure CLI 执行此作。 有关详细信息,请参阅设置 HTTP 并发限制。
仅当未设置自己的 HTTP 并发设置时,上表中的默认并发值才适用。 当您未显式设置 HTTP 并发设置时,默认并发数会根据如表中所示随着实例大小的改变而增加。 在专门设置 HTTP 并发值后,即使实例大小发生更改,该值也会保持不变。
确定每个实例的最佳固定并发水平
固定的每实例并发配置使您可以控制某些触发器行为,例如限制函数的并发速率。 但是很难确定这些设置的最佳值。 通常,必须通过负载测试的迭代过程才能得出可接受的值。 即使您确定了一组适合特定负载配置文件的值,来自连接服务的事件数量也可能每天都变化。 这种可变性可能导致应用使用欠佳值运行。 例如,您的函数应用可能会在一周的最后一天处理高需求的消息负载,这需要您降低并发度。 但是,在本周的其他时间里,消息有效负载可能较轻,这意味着可以在剩下的时间使用更高的并发级别。
理想情况下,系统应允许实例尽可能多地处理工作,同时使每个实例保持正常且延迟较低。 动态并发旨在实现此目的。
动态并发
Functions 提供了一个动态并发模型,用于简化在同一计划中运行的所有函数应用的并发配置。
注意
目前仅支持 Azure Blob 存储、Azure 队列存储和服务总线触发器的动态并发。 必须使用 扩展支持中列出的扩展版本,该部分将在本文后面提到。
优点
动态并发提供以下优势:
- 简化的配置:不再需要手动确定每个触发器的并发设置。 系统会不断地获知工作负载的最佳值。
- 动态调整:可以实时动态调高或调低并发,使系统能够适应不断变化的负载模式。
- 实例运行状况保护:运行时将并发限制为函数应用实例可以轻松处理的级别。 这些限制通过防止应用承担超过其能力的工作来保护应用,避免过载。
- 改进的吞吐量:整体吞吐量得到改善,因为单个实例只拉取它们能够快速处理的工作量。 因此,跨实例更有效地对工作进行负载均衡。 对于可以处理较高负载的函数,可以通过将并发数增加到高于默认配置的值来获取更高的吞吐量。
动态并发配置
可以在 host.json 文件中的主机级别启用动态并发。 启用此功能后,可根据需要自动调整支持此功能的任何绑定扩展的并发级别。 在这些情况下,动态并发设置会替代任何手动配置的并发设置。
默认情况下,动态并发处于关闭状态。 启用动态并发时,并发从每个函数的一个级别开始。 并发级别被提升到主机关定的最佳值。
通过将以下设置添加到 host.json 文件,可以在函数应用中启用动态并发:
{
"version": "2.0",
"concurrency": {
"dynamicConcurrencyEnabled": true,
"snapshotPersistenceEnabled": true
}
}
如果 snapshotPersistenceEnabled
为 true
默认值,则学习的并发值会定期保存到存储中。 新实例从这些值开始,而不是从一个级别开始,并且必须重做学习。
并发管理器
在幕后,当动态并发功能开启时,并发管理器进程自动在后台运行。 此管理器持续监视实例运行状况指标(例如 CPU 和线程利用率),并根据需要更改限制。 打开一个或多个节流机制时,函数并发性会向下调整,直到主机恢复正常状态。 当节流关闭时,并发会提高。 将根据这些限制,使用各种试探法以智能方式按需调高或调低并发。 一段时间后,每个函数的并发将稳定在特定的级别。 由于确定最佳并发值可能需要时间,因此只有在解决方案最初或经过一段时间非活动后,可以接受非最佳值时,才应使用动态并发。
每个函数的并发级别会受到管理。 具体而言,系统在需要低级别的并发和能够处理更高并发的轻型函数的资源密集型函数之间进行平衡。 每个函数的并发平衡有助于维护函数应用实例的整体运行状况。
启用动态并发后,可以在日志中找到动态并发决策。 例如,当激活各种限流机制时,以及每次调整每个函数的并发上下限时,都会添加日志条目。 这些日志在跟踪表中的 Host.Concurrency 日志类别下写入。
扩展支持
动态并发是在主机级别为函数应用启用的,任何支持动态并发的扩展将在该模式下运行。 动态并发需要主机和单个触发器扩展之间的协作。 只有列出的以下扩展版本支持动态并发。
扩展 | 版本 | 说明 |
---|---|---|
队列存储 | 版本 5.x (存储扩展) | 队列存储触发器有自己的消息轮询循环。 使用固定的按实例配置时, BatchSize 和 NewBatchThreshold 配置选项可控制并发性。 使用动态并发时,将忽略这些配置值。 动态并发已集成到消息循环中,因此会动态调整每次迭代检索到的消息数。 开启限流后,主机将过载。 消息处理暂停,直到节流关闭。 当节流关闭时,并发性会增加。 |
Blob 存储 | 版本 5.x (存储扩展) | 在内部,Blob 存储触发器使用的基础结构与队列存储触发器使用的基础结构相同。 需要处理新的或更新的 Blob 时,消息将写入平台管理的控制队列。 该队列使用用于队列存储触发器的相同逻辑进行处理。 当启用动态并发时,将动态管理该控制队列的并发处理。 |
服务总线 | 版本 5.x | 服务总线触发器目前支持三种执行模型。 动态并发通过以下方式影响这些执行模型:MaxConcurrentCalls 配置选项将控制并发。 使用动态并发时,将忽略该配置值,并动态调整并发。MaxConcurrentSessions 设置将控制并发。 启用动态并发时, MaxConcurrentSessions 将忽略该值,并动态调整每个实例进程的会话数。MaxMessageCount 该设置控制。 由于批处理调用是串行的,因此批处理触发的函数的并发始终为一个,并且动态并发不适用。 |
后续步骤
有关详细信息,请参阅以下资源: