速率限制

Google Ads API 会分别针对客户 ID 和 Google Cloud 项目强制执行每秒查询次数 (QPS) 速率限制。除了每分钟请求数(用于衡量 API 调用的频率)之外,Google Ads API 还会强制执行每分钟操作数限制(用于衡量请求中的 API 操作总数)。Google Ads API 使用 令牌桶算法来计量 请求并确定适当的 QPS 限制,因此确切的限制因任何给定时间的整体服务器负载而异。

实施速率限制的目的是防止某个用户有意或无意地发出大量请求,给 Google Ads API 服务器带来过重负担,从而中断其他用户的服务。

违反速率限制的请求会被拒绝,并显示以下错误: RESOURCE_TEMPORARILY_EXHAUSTED.

您可以通过主动减少请求数和从客户端限制 QPS 来控制应用并缓解速率限制。

有多种方法可以降低超出速率限制的可能性。 熟悉 企业集成模式 (EIP) 概念(例如消息传递、重新传送和限制)有助于您构建更 强大的客户端应用。

以下建议的做法按复杂程度排序,简单的策略位于顶部,更强大但更复杂的架构位于后面:

指数退避算法

当您的应用收到 RESOURCE_TEMPORARILY_EXHAUSTED错误时,请使用 指数退避算法政策并添加随机抖动,然后再重试失败的 请求。指数退避算法会逐步增加重试之间的等待时间(例如,等待 2 秒,然后等待 4 秒,再等待 8 秒,外加一小段随机延迟时间),以便服务器负载和配额桶能够恢复,同时防止客户端实例出现同步重试峰值。

限制并发任务数

导致速率超限的一个根本原因是客户端应用产生了过多的并行任务。虽然我们不会限制客户端应用可以拥有的并行请求数,但此数量可能会超出 Google Cloud 云项目级别的每秒请求数 限制。

我们建议对所有进程和机器上将会发送请求的并行任务总数设置合理的上限,并以之为基础向上调整,从而在不超出速率限制的情况下优化吞吐量。

此外,您可以考虑从客户端限制 QPS(请参阅 限流和使用速率限制器)。

批量请求

考虑将多个操作批量处理到单个请求中。这最适用于各种服务的 Mutate 调用。例如,如果您要更新多个 AdGroupAd 实例的状态,则可以调用一次 MutateAdGroupAds,并传入多个 operations,而不是针对每个 AdGroupAd 调用一次 MutateAdGroupAds。如需了解更多 示例,请参阅我们的 批量操作指南。

虽然批量请求会减少 API 调用总数并缓解 每分钟请求数的速率限制,但如果您针对单个 账号执行大量操作,则可能会触发每分钟操作数速率限制。

限流和使用速率限制器

除了限制应用中的线程总数之外,您还可以在客户端实现速率限制器。这样可以确保您的进程、集群或两者中的所有线程都受客户端的特定 QPS 限制的约束。

请参阅 Guava RateLimiter,或为集群环境实现您自己的 令牌桶算法。例如,您可以在分布式低延迟内存数据存储区(例如 Redis 或 Memcached)中管理令牌,其中每个客户端在处理请求之前获取并使用令牌。如果令牌用完,客户端会等待下一批令牌补充完毕。

队列

消息队列是用于分配操作负载的解决方案,同时还可以控制请求和使用者速率。可用的消息队列方案有许多:一些是开源的,一些是专有的,而且其中许多都支持各种不同的语言。

在使用消息队列时,您可以有多个推送消息到队列的生成者和多个处理这些消息的使用者。您可以通过限制并发使用者的数量,或者为生成者或使用者实现速率限制器或限流器,在使用者端实现限流。

例如,如果消息使用者遇到速率限制错误,该使用者可以使用标准化重试延迟时间(使用指数退避算法)将请求返回到队列,并更新共享速率限制器反馈循环,以便所有使用者在从错误中恢复时自动降低其处理速率。