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

诊断并排查“请求速率过大”(429)异常

“请求速率过大”异常(也称为“错误代码 429”)表示,针对 Azure Cosmos DB 提出请求时,请求速率受限。

本文包含 API for NoSQL 的各种 429 状态代码错误的已知原因和解决方案。 如果使用的是用于 MongoDB 的 API,请参阅 用于 MongoDB 的 API 中的常见问题疑难解答

若要使用预配吞吐量,可以工作负载所需的每秒请求单位 (RU/s) 为单位设置吞吐量。 针对服务的数据库操作(如读取、写入和查询)会消耗一定数量的请求单元 (RU)。 详细了解请求单元

在某一秒内,如果操作的消耗量超过预配的请求单位,Azure Cosmos DB 将返回 429 错误。 每秒重置可用的请求单位数。

在采取措施更改 RU/s 之前,必须了解速率限制的根本原因并解决基础问题。

小窍门

本文中的指导适用于使用预配置吞吐量(自动缩放和手动吞吐量)的数据库和容器。

存在对应不同类型的 429 异常的不同错误消息:

请求速率过大

这是最常见的情况。 当对数据进行操作消耗的 RU 超过配置的 RU 数时,会发生此情况。 当您使用手动配置的吞吐量时,如果您消耗的 RU/秒超过了手动配置的吞吐量,将会出现此情况。 如果您使用自动扩展,当您使用量超过预配的最大 RU/秒时,会发生这种情况。 例如,如果资源被配置为手动吞吐量为 400 RU/秒,那么当在一秒内消耗超过 400 个请求单位时,将会收到 429 状态码。 如果一个资源被预配为具有最大 4000 RU/秒的自动扩展功能(在 400 RU/秒到 4000 RU/秒之间扩展),当在某一秒内消耗超过 4000 请求单位时,您将看到 429 响应。

小窍门

所有作都根据消耗的资源数收费。 这些费用以请求单位为单位进行度量。 这些费用包括由于应用程序错误(如 400412 和 449)而未成功完成的请求。 在查看限制或使用情况时,最好调查某些使用模式是否发生了更改,从而导致这些操作的增加。 具体而言,检查标记 412449 (实际冲突)。

有关预配吞吐量的详细信息,请参阅 Azure Cosmos DB 中预配的吞吐量简介

第 1 步:检查指标,确定出现 429 错误的请求百分比

看到 429 错误消息并不一定意味着数据库或容器出现问题。 无论是使用手动还是自动缩放的吞吐能力,429 个响应的一小部分都是正常的,这表明你正在最大程度地提高预配的每秒请求单元 (RU/s)。

调查方式

与成功请求的总计数进行比较,确定出现 429 响应错误的数据库或容器请求所占的百分比。 从“Azure Cosmos DB 帐户”中,导航到见解>请求>按状态代码显示的请求总数。 筛选到特定数据库和容器。

默认情况下,Azure Cosmos DB 客户端 SDK 和数据导入工具(如 Azure 数据工厂和批量执行工具库)会自动重试提交出现 429 错误的请求。 重试次数通常最多为九次。 因此,虽然可以在指标中看到 429 个响应,但这些错误甚至可能尚未返回到应用程序。

“按状态代码排序的请求总数”图表的屏幕截图,其中显示了 429 个和 2xx 个请求数。

通常,对于生产工作负荷,如果您观察到 1-5% 的请求返回 429 响应状态码,并且端到端延迟是可以接受的,则这表明 RU/s 正在被充分利用。 无需执行任何操作。 否则,请继续执行接下来的故障排除步骤。

重要

此 1-5% 范围假定帐户分区均匀分布。 如果分区未均匀分布,则问题分区可能会返回大量 429 错误,而总体速率可能较低。

如果使用自动缩放,即使 RU/秒值未扩展到最大 RU/秒,也可能会在数据库或容器上看到 429 响应错误。 有关说明,请参阅 “请求速率较大并且自动缩放”部分

客户提出的一个常见问题是,“为何我在 Azure Monitor 指标中看到了 429 响应错误,但在我自己的应用程序监视中却没有看到?”如果 Azure Monitor 指标显示了 429 响应错误,但你在自己的应用程序中未看到这种错误,则原因是默认情况下,Azure Cosmos DB 客户端 SDK automatically retried internally on the 429 responses 和请求在后续的重试中已成功。 因此,不会向应用程序返回 429 状态代码。 在这种情况下,429 响应错误的总体比率通常最小(假设总体比率为 1-5%),可以放心地忽略,并且端到端延迟对于应用程序是可接受的。

步骤 2:确定是否存在热分区

当一个或几个逻辑分区键由于请求量较高而消耗了过多的总 RU/s 时,即会出现热分区。 而造成这一情况的原因可能是分区键设计导致请求未能均匀分布。 这会导致许多请求被定向到几个逻辑分区(也就是物理分区)的小子集,这些分区会变成热点。 由于逻辑分区的所有数据都驻留在一个物理分区上,RU/s 总数均匀分布在物理分区之间,因此热分区可能会导致 429 个响应和低效的吞吐量使用。

下面是导致热分区的一些分区策略示例:

  • 你有一个容器,用于存储通过 date 分区的写入密集型工作负载的 IoT 设备数据。 单个日期的所有数据都驻留在同一逻辑分区和物理分区上。 由于每天写入的所有数据都具有相同的日期,因此每天都会生成热分区。

    • 相反,在这种情况下,使用类似id(例如 GUID 或设备 ID)作为分区键,或者使用合成分区键(通过组合iddate),可以得到更高的值基数,并更好地分配请求量。
  • 你有一个多租户场景,其中的容器是按 tenantId 分区的。 如果一个租户的活跃性明显高于其他租户,则会导致热分区。 举例来说,如果最大租户有 100,000 名用户,但大多数租户的用户数少于 10 人,则按 tenantID 分区时,将会产生热分区。

    • 对于上述方案,应考虑为最大租户创建专用容器,并按更精细的属性(如 UserId)进行分区。

如何识别热分区

若要验证是否存在热分区,请导航到见解>吞吐量>按 PartitionKeyRangeID 列出的规范化 RU 消耗量 (%)。 筛选到特定数据库和容器。

每个分区键范围 ID 映射到一个物理分区。 如果有一个 PartitionKeyRangeId 比其他分区高得多的 规范化 RU 消耗 (例如,一个始终在 100%,但其他分区为 30% 或更少),则可以是热分区的标志。 若要详细了解规范化 RU 消耗指标,请参阅 如何监视 Azure Cosmos DB 容器或帐户的规范化 RU/s

屏幕截图显示了带有热分区的 PartitionKeyRangeId 图表中的规范化 RU 消耗。

若要查看哪些逻辑分区键使用最多的 RU/秒,请使用 Azure 诊断日志。 此示例查询汇总了每个逻辑分区键每秒消耗的请求单位总数。

重要

启用诊断日志将单独产生 Log Analytics 服务费(按引入的数据量计费)。 建议出于调试目的启用诊断日志有限的一段时间,在不需要诊断日志时将其禁用。 若要了解详细信息,请参阅Azure Monitor 定价

 CDBPartitionKeyRUConsumption
 | where TimeGenerated >= ago(24hour)
 | where CollectionName == "CollectionName"
 | where isnotempty(PartitionKey)
 // Sum total request units consumed by logical partition key for each second
 | summarize sum(RequestCharge) by PartitionKey, OperationName, bin(TimeGenerated, 1s)
 | order by sum_RequestCharge desc

此示例输出显示,在特定分钟内,值为 Contoso 的逻辑分区键消耗了大约 12,000 RU/秒,而值为 Fabrikam 的逻辑分区键消耗了小于 600 RU/秒。 如果此模式在速率受限发生期间一直存在,则表明存在热分区。

显示逻辑分区键每秒消耗最大请求单位的结果的屏幕截图。

小窍门

在任何工作负荷中,请求数量在逻辑分区之间自然变化。 你应当确定导致产生热分区的原因是因分区键选择造成的基本偏斜(可能需要更改分区键)还是因工作负荷模式的自然变化而暂时出现峰值。

查看有关如何选择良好分区键的指导。

如果受到速率限制的请求百分比较高,但未出现热分区:

如果受到速率限制的请求百分比较高,并出现了根本性的热分区:

  • 从长远来看,为了获得最佳成本和性能,请考虑 更改分区键。 无法就地更新分区键,因此,这需要将数据迁移到具有不同分区键的新容器。 Azure Cosmos DB 支持使用实时数据迁移工具来实现此目的。
  • 短期内,可以暂时提高资源的总体 RU/秒,以便让热分区拥有更多的吞吐能力。 不建议将此用作长期策略,因为它会导致每秒 RU 数过度预配和增加成本。
  • 短期内,可以 跨分区重新分配吞吐量(预览版), 以便将更多 RU/秒分配给热的物理分区。 仅当热物理分区可预测且稳定一致时,才建议这样做。

小窍门

增加吞吐量时,横向扩展操作可以即时完成,或者需要长达 5-6 小时才能完成,具体取决于您要扩展到的 RU/s 数量。 若要了解在不触发异步纵向扩展操作(需要使用 Azure Cosmos DB 预配更多物理分区)的情况下,可以设置的最高 RU/s 数,请将不同的分区键范围 ID 乘以 100,000 RU/s。 例如,如果预配了 30,000 RU/s 和 5 个物理分区(每个物理分区分配 6000 RU/秒),则可以在即时纵向扩展作中增加到 50,000 RU/秒(每物理分区 10,000 RU/秒)。 但若要将 RU/s 数增至 50,000 RU/s 以上,则需要执行异步纵向扩展操作。 若要了解详细信息,请参阅 有关缩放预配吞吐量(RU/s)的最佳做法

步骤 3:确定返回 429 响应错误的请求

如何调查出现 429 响应错误的请求

使用 Azure 诊断日志来确定返回 429 响应错误的请求,以及这些请求消耗的 RU 数。 此示例查询按分钟聚合。

重要

启用诊断日志将单独产生 Log Analytics 服务费(按引入的数据量计费)。 建议出于调试目的启用诊断日志有限的一段时间,在不需要诊断日志时将其禁用。 若要了解详细信息,请参阅Azure Monitor 定价

 CDBDataPlaneRequests
 | where TimeGenerated >= ago(24h)
 | summarize throttledOperations = dcountif(ActivityId, StatusCode == 429), totalOperations = dcount(ActivityId), totalConsumedRUPerMinute = sum(RequestCharge) by DatabaseName, CollectionName, OperationName, RequestResourceType, bin(TimeGenerated, 1min)
 | extend averageRUPerOperation = 1.0 * totalConsumedRUPerMinute / totalOperations
 | extend fractionOf429s = 1.0 * throttledOperations / totalOperations
 | order by fractionOf429s desc

例如,此示例输出显示,每分钟有 30% 的创建文档请求受到速率限制,而每个请求平均消耗 17 个请求单位(RU)。

显示诊断日志中状态码为 429 的请求的屏幕截图。

使用 Azure Cosmos DB 容量规划器

可以使用 Azure Cosmos DB 容量规划器,了解什么是基于工作负载(操作量和类型以及文档大小)的最佳预配吞吐量。 可以通过提供示例数据来进一步自定义计算,以获得更准确的估计。

创建、替换或更新插入文档请求时出现 429 响应错误

默认情况下,API for NoSQL 会默认对所有属性都编制索引。 你可以调整索引策略,以仅对所需属性编制索引。 这会降低每个创建文档操作所需的 RU,从而减少出现 429 响应的可能性,或者允许你在相同预配的 RU/秒下实现更高的每秒操作次数。

查询文档请求时出现 429 响应错误

按照指南 排查 RU 费用过高的查询问题。

执行存储过程时出现 429 响应错误

存储过程适用于需要跨分区键值写入事务的操作。 不建议将存储过程用于大量的读取或查询操作。 要获得最佳性能,应在客户端使用 Azure Cosmos DB SDK 完成这些读取或查询操作。

使用自动缩放时请求速率过大

本文中的所有指导适用于手动吞吐量和自动缩放吞吐量。

使用自动缩放时,出现的一个常见问题是 “是否可以使用自动缩放查看 429 个响应?”

答案是 肯定的。 有两种主要方案可以发生这种情况:

方案 1:当消耗的总 RU/秒超过数据库或容器的最大 RU/秒时,服务会相应地限制请求。 这类似于超过了数据库或容器的总体手动预配吞吐量。

方案 2:如果有热分区(即逻辑分区键值)与其他分区键值相比请求量不成比例地高,则基础物理分区可能超出其 RU/秒预算。 为避免出现热分区,最佳做法是选择良好的分区键,从而实现存储和吞吐量的均匀分布。 这类似于使用手动吞吐量时存在热分区的情况。

例如,如果选择“20,000 RU/秒最大吞吐量”选项,并且 200 GB 的存储空间包含 4 个物理分区,则每个物理分区最多可以自动扩展到 5000 RU/秒。 如果某个特定逻辑分区键上存在热分区,则当它所在的基础物理分区超过 5000 RU/秒(即超出了 100% 的标准化利用率)时,将会出现 429 响应错误。

按照步骤 1步骤 2步骤 3 中的指导针对这些场景进行调试。

另一个常见问题是,为何规范化 RU 消耗量 100%,但自动缩放未扩展到最大 RU/秒?

这种情况通常发生在临时或间歇性达到使用量高峰的工作负载上。 使用自动缩放时,仅当规范化 RU 消耗量在 5 秒间隔内持续稳定地保持 100% 时,Azure Cosmos DB 才会将 RU/秒扩展到最大吞吐量。 这是为了确保缩放逻辑的成本对用户可接受,避免单次短暂性的高峰导致不必要的扩展和提高成本。 在出现短暂性的高峰时,系统通常会扩展到一个比上次所扩展到的 RU/秒更高,但比最大 RU/秒更低的值。 如需了解更多信息,请参阅 规范化 RU 消耗和自动缩放

元数据请求速率受限

对数据库和/或容器执行大量元数据操作时,可能会发生元数据速率受限问题。 元数据操作包括:

  • 创建、读取、更新或删除容器或数据库
  • 列出 Azure Cosmos DB 帐户中的数据库或容器
  • 查询产品/服务,以查看当前预配的吞吐量

对于这些操作,系统有保留的 RU 限制,因此增加数据库或容器的预配的 RU/s 并不起作用,不建议这样做。 请参阅控制平面服务限制

调查方式

导航到见解>系统>按状态代码显示的元数据请求。 根据需要,筛选到特定数据库和容器。

Insights 中按状态代码图表显示元数据请求的屏幕截图。

  • 如果应用程序需要执行元数据操作,请考虑实施回退策略以降低该等请求的发送速率。

  • 使用静态 Azure Cosmos DB 客户端实例。 初始化 DocumentClient 或 CosmosClient 时,Azure Cosmos DB SDK 将提取有关该帐户的元数据,包括与一致性级别、数据库、容器、分区以及产品/服务相关的信息。 此初始化可能会消耗大量 RU,并且不经常执行。 在应用程序的生存期内使用单个 DocumentClient 实例。

  • 缓存数据库和容器名称。 从配置检索数据库和容器的名称,或者一开始就缓存名称。 调用(如 ReadDatabaseAsync/ReadDocumentCollectionAsync 或 CreateDatabaseQuery/CreateDocumentCollectionQuery)会导致对服务进行元数据调用,这会消耗系统预留的 RU 限额。 因此,你应该避免频繁执行此类操作。

因暂时性服务错误而导致速率受限

当请求遇到暂时性服务错误时,系统将返回此 429 错误。 增加数据库或容器上的 RU/s 不起作用,不建议这样做。

重试请求。 如果数分钟后错误仍然存在,请从 Azure 门户提交支持票证。

后续步骤