你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用范围: NoSQL
本文包含 API for NoSQL 的各种 429 状态代码错误的已知原因和解决方案。 如果你使用的是 API for MongoDB,请参阅排查 API for MongoDB 中的常见问题一文来了解如何调试状态代码 16500。
“请求速率过大”异常(也称为“错误代码 429”)表示,针对 Azure Cosmos DB 提出请求时,请求速率受限。
若要使用预配吞吐量,可以工作负载所需的每秒请求单位 (RU/s) 为单位设置吞吐量。 针对服务的数据库操作(如读取、写入和查询)会消耗一定数量的请求单元 (RU)。 详细了解请求单元。
在某一秒中,如果操作消耗的请求单位数超过预配数,Azure Cosmos DB 将返回 429 异常。 每秒重置可用的请求单位数。
在采取措施更改 RU/s 之前,必须了解速率受限的根本原因并解决根本问题。
提示
本文中的指导适用于使用预配置吞吐量(自动缩放和手动吞吐量)的数据库和容器。
存在对应不同类型的 429 异常的不同错误消息:
请求速率太大
这是最常见的情况。 当数据操作消耗的请求单位数超过预配的 RU/s 数时,即会发生这种情况。 如果使用手动吞吐量,则当每秒消耗的 RU 数多于预配的手动吞吐量时,就会发生这种情况。 如果使用自动缩放,则当消耗的 RU 数超过预配的最大每秒 RU 数时,就会发生这种情况。 例如,如果为某个资源预配的手动吞吐量为 400 RU/秒,则当一秒内消耗的请求单位数超过 400 个时,将会出现 429 错误。 如果为某个资源预配的自动缩放最大每秒 RU 数为 4000 RU/秒(在 400 RU/秒与 4000 RU/秒之间缩放),则当一秒内消耗的请求单位数超过 4000 个时,将会出现 429 响应错误。
提示
所有操作会根据它们使用的资源数收费。 这些费用按请求单位度量。 这些费用包括由于应用程序错误(如 400、412、449等)而未成功完成的请求。在查看限制或使用情况时,最好调查使用中某些模式是否发生了更改,从而导致这些操作增加。 具体而言,检查标记 412 或449(实际冲突)。
有关预配吞吐量的详细信息,请参阅 Azure Cosmos DB 中的预配吞吐量。
第 1 步:检查指标,确定出现 429 错误的请求百分比
看到 429 错误消息并不一定表示数据库或容器存在问题。 无论是使用手动吞吐量还是自动缩放吞吐量,出现一小部分 429 响应错误都属正常情况,这表示即将达到预配的最大每秒 RU 数。
调查方式
与成功请求的总计数进行比较,确定出现 429 响应错误的数据库或容器请求所占的百分比。 从“Azure Cosmos DB 帐户”中,导航到“见解”“请求”>“按状态代码显示的请求总数”。 筛选到特定数据库和容器。
默认情况下,Azure Cosmos DB 客户端 SDK 和数据导入工具(如 Azure 数据工厂和批量执行工具库)会自动重试提交出现 429 错误的请求。 重试次数通常最多为九次。 因此,虽然指标中可能会显示 429 响应错误,但这些错误甚至可能尚未返回到应用程序。
建议的解决方案
一般情况下,对于生产工作负载而言,如果看到出现 429 响应错误的请求百分比在 1% - 5% 之间,并且端到端延迟可接受,那么这就是一个可以表明 RU/s 受到充分利用的良好迹象。 不需要执行任何操作。 否则,请继续执行接下来的故障排除步骤。
重要
此 1-5% 范围的假设前提是你的帐户分区分布均匀。 如果你的分区分布不均匀,则问题分区可能会返回大量 429 错误,而总体速率可能较低。
如果使用自动缩放,即使 RU/秒值未扩展到最大 RU/秒,也可能会在数据库或容器上看到 429 响应错误。 有关说明,请参阅使用自动缩放时请求速率过大部分。
客户提出的一个常见问题是,“为何我在 Azure Monitor 指标中看到了 429 响应错误,但在我自己的应用程序监视中却没有看到?”如果 Azure Monitor 指标显示了 429 响应错误,但你在自己的应用程序中未看到这种错误,则原因是默认情况下,Azure Cosmos DB 客户端 SDK 和请求在后续的重试中已成功。 因此,不会向应用程序返回 429 状态代码。 在这种情况下,429 响应错误的总体比率通常最小(假设总体比率为 1-5%),可以放心地忽略,并且端到端延迟对于应用程序是可接受的。
步骤 2:确定是否存在热分区
当一个或几个逻辑分区键由于请求量较高而消耗了过多的总 RU/s 时,即会出现热分区。 而造成这一情况的原因可能是分区键设计导致请求未能均匀分布。 这会导致许多请求被定向到变“热”的一小部分逻辑(这里表示物理)分区。由于逻辑分区的所有数据都驻留在一个物理分区上,并且总 RU/s 在物理分区之间均匀分布,因此,热分区可能导致吞吐量的 429 响应和低效使用。
下面是导致热分区的一些分区策略示例:
- 你有一个用于存储 IoT 设备写入密集型工作负载数据的容器,并按
date进行分区。 单个日期的所有数据将驻留在同一逻辑分区和物理分区中。 由于每天写入的所有数据的日期都相同,因此会导致每天都产生热分区。 - 你有一个多租户方案,使用的容器按
tenantId进行分区。 如果一个租户的活跃性明显高于其他租户,则会导致热分区。 举例来说,如果最大租户有 100,000 名用户,但大多数租户的用户数少于 10 人,则按tenantID分区时,将会产生热分区。- 对于上述方案,应考虑为最大租户创建专用容器,并按更精细的属性(如
UserId)进行分区。
- 对于上述方案,应考虑为最大租户创建专用容器,并按更精细的属性(如
如何识别热分区
若要验证是否存在热分区,请导航到“见解”“吞吐量”>“按 PartitionKeyRangeID 列出的规范化 RU 消耗量(%)”。 筛选到特定数据库和容器。
每个分区键范围 ID 映射到一个物理分区。 如果某个 PartitionKeyRangeId 的规范化 RU 消耗量明显高于其他 PartitionKeyRangeId(例如,一个 PartitionKeyRangeId 的消耗量一直为 100%,而其他 PartitionKeyRangeId 的消耗量不超过 30%),则可能表示存在热分区。 详细了解规范化 RU 消耗量指标。
如需了解消耗 RU/s 最多的逻辑分区键,请查阅 Azure 诊断日志。 此示例查询汇总了每个逻辑分区键每秒消耗的请求单位总数。
重要
启用诊断日志将单独产生 Log Analytics 服务费(按引入的数据量计费)。 建议出于调试目的启用诊断日志有限的一段时间,在不需要诊断日志时将其禁用。 请参阅定价页面了解详细信息。
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/s,而值为“Fabrikam”的逻辑分区键的消耗量则少于 600 RU/s。 如果此模式在速率受限发生期间一直存在,则表明存在热分区。
提示
在任何工作负载中,跨逻辑分区的请求量都存在自然变化。 你应当确定导致产生热分区的原因是因分区键选择造成的基本偏斜(可能需要更改分区键)还是因工作负荷模式的自然变化而暂时出现峰值。
建议的解决方案
查看有关如何选择良好分区键的指导。
如果受到速率限制的请求百分比较高,但未出现热分区:
- 可以使用客户端 SDK、Azure 门户、PowerShell、CLI 或 ARM 模板来增加数据库或容器的 RU/s。 按照缩放预配吞吐量(RU/秒)的最佳做法,确定要设置的正确 RU/秒。
如果受到速率限制的请求百分比较高,并出现了根本性的热分区:
- 从长期来看,为获得最佳成本效益和性能,应考虑更改分区键。 无法就地更新分区键,因此,这需要将数据迁移到具有不同分区键的新容器。 Azure Cosmos DB 支持使用实时数据迁移工具来实现此目的。
- 短期而言,你可以暂时增大资源的总体 RU/秒,以提高热分区的吞吐量。 不建议将此用作长期策略,因为它会导致每秒 RU 数过度预配和增加成本。
- 短期内,可以使用跨分区吞吐量重新分配功能(预览版)为热物理分区分配更多的 RU/秒。 仅当热物理分区可预测且稳定一致时,才建议这样做。
提示
增加吞吐量时,纵向扩展操作可能会即时或最多需要 5-6 小时完成,具体视要纵向扩展的 RU/s 数量而定。 如果想要知道可以设置的最大 RU/秒数,而无需触发异步纵向扩展作(这要求 Azure Cosmos DB 预配更多物理分区),请将不同的 PartitionKeyRangeIds 数乘以 10,000 RU/秒。 例如,如果已预配 30,000 RU/s 及 5 个物理分区(每个物理分区已分配 6,000 RU/s),则可以在即时纵向扩展操作中将 RU/s 数增至 50,000 RU/s(每个物理分区 10,000 RU/s)。 但若要将 RU/s 数增至 50,000 RU/s 以上,则需要执行异步纵向扩展操作。 在有关缩放预配吞吐量(RU/秒)的最佳做法中了解详细信息。
步骤 3:确定返回 429 响应错误的请求
如何调查出现 429 响应错误的请求
使用 Azure 诊断日志来确定返回 429 响应错误的请求,以及这些请求消耗的 RU 数。 此示例查询按分钟聚合。
重要
启用诊断日志将单独产生 Log Analytics 服务费(按引入的数据量计费)。 我们建议你在有限时间内启用诊断日志进行调试;若不再需要时,建议关闭诊断日志。 请参阅定价页面了解详细信息。
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 个请求单位。
建议的解决方案
使用 Azure Cosmos DB 容量规划器
可以使用 Azure Cosmos DB 容量规划器,了解什么是基于工作负载(操作量和类型以及文档大小)的最佳预配吞吐量。 可以通过提供示例数据来进一步自定义计算,以获得更准确的估计。
创建、替换或更新插入文档请求时出现 429 响应错误
- 默认情况下,API for NoSQL 会默认对所有属性都编制索引。 你可以调整索引策略,以仅对所需属性编制索引。 这将减少每个创建文档操作所需的请求单位数,从而降低看到 429 响应错误的可能性,或者允许你在使用相同数量预配 RU/s 的情况下,每秒执行更多操作。
查询文档请求时出现 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 数没有任何效果,我们也不建议这样做。 请参阅控制平面服务限制。
调查方式
导航到“见解”“系统”>“按状态代码显示的元数据请求”。 根据需要,筛选到特定数据库和容器。
建议的解决方案
如果应用程序需要执行元数据操作,请考虑实施回退策略以降低该等请求的发送速率。
使用静态 Azure Cosmos DB 客户端实例。 初始化 DocumentClient 或 CosmosClient 时,Azure Cosmos DB SDK 将提取有关该帐户的元数据,包括与一致性级别、数据库、容器、分区以及产品/服务相关的信息。 此初始化可能需要使用大量 RU,不应频繁执行。 在应用程序的生存期内使用单个 DocumentClient 实例。
缓存数据库和容器名称。 从配置中检索数据库和容器的名称,或者一开始就将其缓存。 ReadDatabaseAsync/ReadDocumentCollectionAsync 或 CreateDatabaseQuery/CreateDocumentCollectionQuery 等调用将导致元数据调用相关服务,而该等调用将会消耗系统保留的有限 RU。 因此,你应该避免频繁执行此类操作。
因暂时性服务错误而导致速率受限
当请求遇到暂时性服务错误时,系统将返回此 429 错误。 增大数据库或容器的每秒 RU 数没有任何效果,不建议这样做。
建议的解决方案
重试请求。 如果数分钟后错误仍然存在,请从 Azure 门户提交支持票证。
后续步骤
- 监视数据库或容器的规范化 RU/s 消耗量。
- 诊断和排查在使用 Azure Cosmos DB .NET SDK 时遇到的问题。
- 了解 .NET v3 和 .NET v2 的性能准则。
- 诊断和排查使用 Azure Cosmos DB Java v4 SDK 时遇到的问题。
- 了解 Java v4 SDK 的性能准则。