速率限制是一种关键的控制机制,用于管理 API 的请求流,非常类似于调节器。速率限制不仅仅是控制请求的总数,它还关系到如何以及在哪里应用这些限制。根据 API 的需要,可以根据各种因素(如用户 ID、 IP 地址或特定类型的 API 调用)来实现速率限制。
例如,一个社交平台可能实施严格的速率限制,以防止发布垃圾邮件,同时允许更频繁的请求阅读内容。类似地,服务可以对来自已知用户和匿名流量的请求应用不同的限制,使用用户 ID 或 IP 地址来区分。这种灵活性使得速率限制成为一种通用的工具,不仅可以防止过载,而且可以创造一种公平和平衡的用户体验。
1. API限速的主要作用
API 速率限制能够防止DoS攻击,确保API对合法用户开放;同时,它还能公平分配资源,降低运营成本,并有效管理第三方API的计费和配额,避免意外费用。
- 防止拒绝服务(DoS)攻击: 正如商场可能会限制进入以防止过度拥挤一样,速率限制可以防止恶意用户用过多的请求淹没 API,从而导致拒绝服务攻击。这使得 API 对合法用户可用。
- 资源公平分配: 它确保 API 的资源在所有用户之间均匀分配。如果没有速率限制,少数重度用户可能会消耗超过其合理份额的资源,从而降低其他用户的服务质量。
- 管理运营成本: 特别是在基于云的环境中,处理大量 API 请求的成本可能很高。利率限制有助于控制这些成本,防止过度使用。
- 第三方 API 计费: 当 API 作为第三方服务的一部分使用时,速率限制对于管理计费和使用配额是至关重要的。它确保用户保持在分配的使用限制内,避免意外的费用。
那么, 我们常用的API 限速方法有哪些呢?
2. 令牌桶(Token Bucket)
令牌桶是一种用于管理网络流量的方法,其中的令牌按规则的间隔添加。对 API 的每个请求都需要一个令牌。如果 bucket 没有令牌,请求将被拒绝,从而确保 API 不会过载。
图片
每个令牌表示发送一定数量数据的权限(如 API 请求)。当请求到达时,只有当令牌可用时才能处理该请求,然后将令牌从 bucket 中删除。如果 bucket 为空,则请求必须等待,直到添加新标记。例如, bucket 每秒添加5个令牌,并且每个令牌允许一个 API 请求,则最多可以处理每秒5个请求。如果请求的活跃度较低,令牌会累积,只要有足够的令牌,每秒可以处理5个以上的请求,这就允许偶尔的爆发。
通过令牌桶,我们可以控制用户在给定时间段内可以发出的请求数,从而防止服务器过载。并且,可以帮助在用户或应用程序之间分配可用带宽,确保公平使用和防止拥塞。
令牌桶的局限性如下:
- 高速网络中的复杂性: 在极高速或复杂的网络环境中,维护令牌存储桶的开销可能很大。
- 不对流量进行优先排序: 它平等对待所有请求,在某些请求应该具有优先级的系统中,这可能并不理想。
- 突发处理不够灵活: 设置正确的令牌速率和桶大小需要理解典型的流量模式,这可能并不简单。
3. 漏桶(leak bucket)
漏桶也是一种用于网络流量管理和 API 速率限制的方法,重点是保持一致的输出速率。我们可以将 Bucket 想象为以稳定的速度不断泄漏请求。如果请求(水)来得太快,而桶被填满,多余的请求就会溢出并丢失,类似于被拒绝或排队。
图片
对比而言,只要令牌桶中有令牌,它就允许流量进入,令牌随时间积累,允许灵活处理突然增加的流量。而漏桶更加严格,它以恒定的速率泄漏请求。桶有多满并不重要,目标是输出速率保持不变。这可能导致在低流量期间利用率不足,却又无法容纳突发的流量。例如,使用漏桶的 API 可能以每秒5个的固定速率处理请求,而不管有多少请求处于等待之中。相反,对于 令牌桶,如果有足够的令牌,它可以在一秒钟内处理突发的20个请求,然后在令牌用完时返回较慢的速率。
漏桶对于需要一致数据流的网络非常有用,可以用于网络流量整形。虽然没有令牌桶灵活,但是它适用于流量稳定的 API。同时,避免了突发的流量高峰,有助于防止拥塞。
漏桶的局限性:
- 无突发处理: 不像令牌桶,它不能有效地处理突然的流量峰值。
- 潜在的利用率不足: 在低流量时可能导致容量冗余。
- 一致但不灵活: 虽然它确保了一个稳定的速率,但它缺乏对不断变化的流量的适应性,而这对于某些应用程序可能是必要的。
4. 固定窗口计数器
固定窗口计数器是一种用于管理 API 请求和网络流量的速率限制策略,基于对在指定时间窗口内可以发出的请求数量设置固定的限制。在这种方法中,将时间划分为固定的间隔或窗口,并为每个窗口设置允许的最大请求数。一旦达到该窗口内的限制,在下一个窗口启动之前不会再接受任何请求。
图片
令牌桶和漏桶允许在处理请求速率方面有一定的灵活性,而固定窗口计数器是更严格的意义上限制。如果请求快速地达到了限制,则在下一个窗口之前不会处理更多请求,而不管实际的容量或需求如何。考虑一个速率限制为每小时100个请求的 API。在固定窗口计数器下,如果在最初30分钟内收到100个请求,则不论服务器的实际容量或需求如何,在该小时的剩余30分钟内将不会处理进一步的请求。
在电子商务中,通过固定窗口计数器,我们可以限制用户可以在设定的时间框架内发起的交易数量来确保交易过程的安全性,从而增强防范欺诈的安全性。在云服务中,通过对启动或停止虚拟机等操作的 API 调用设置限制来控制资源使用,从而确保公平的资源分配。我们还可以管理从物联网设备到服务器的数据传输,这对于防止服务器过载和促进间隔数据分析至关重要。
固定窗口计数器的局限性:
- 流量突发的不灵活性: 与令牌桶不同,它不能适应窗口内流量的突然激增。
- 低效的可能性: 可能导致使用不足的周期,特别是如果在窗口的早期就达到了极限。
- “窗口重置”问题: 用户可能会在新窗口开始时遇到突然涌入的允许请求,这可能会造成不均衡的服务器负载。
- 窗口边缘突发问题: 一个重大缺陷是易受窗口边缘流量突发的影响。考虑这样一个场景: 在窗口重置之前有大量请求进入,并且在重置之后立即发生类似的激增。这可能导致在短时间内处理的请求超过预期的配额,从而可能使系统不堪重负。这种“窗口边缘”的突发可以在服务器负载中产生峰值,并降低速率限制策略的有效性。
5. 滑动窗口日志
滑动窗口日志是一种复杂的 API 速率限制和网络流量管理方法。与固定窗口不同,此方法考虑每个单独请求的时间,提供了更动态的方法。它保存了每个传入请求的时间戳的日志。然后根据当前滑动窗口(一个连续移动的时间框架)中的请求数确定速率限制。如果此窗口中的请求数超过阈值,新请求将被拒绝或排队。
图片
固定窗口计数器对静态时间窗口施加严格的限制,导致每个窗口边缘的潜在爆发。滑动窗口日志提供了一个更动态的方法,随着时间的推移不断调整。这可以防止在固定窗口的重置点常见的突发流量。例如,一个 API 每分钟限制100个请求。在滑动窗口日志中,此限制在过去一分钟内不断进行评估。如果有请求进入,滑动窗口日志会在最后60秒内检查所有请求。如果该数字小于100,则允许请求; 否则,将拒绝请求。
滑动窗口日志的局限性:
- 资源密集型约束: 维护所有请求的日志可能需要计算,特别是对于大量请求。
- 复杂实现: 与固定窗口计数器相比,其动态特性使实现更加复杂。
- 潜在延迟: 在流量极大的情况下,滑动窗口的连续计算会引入延迟。
6. 滑动窗口计数器
滑动窗口计数器结合了固定窗口计数器和滑动窗口日志方法的元素,旨在以更平衡的方式管理网络流量和 API 请求。它跟踪滚动时间框架内的请求数,这与固定时间间隔不同。它计算当前窗口中的请求,同时也考虑来自前一窗口的部分请求,从而在时间间隔之间提供更平滑的转换。
图片
滑动窗口日志维护了单个请求时间戳的日志,而该请求可能是资源密集型的。滑动窗口计数器通过对滚动窗口中的请求进行计数,减少了与记录每个请求的时间戳相比的计算开销,从而简化了这一过程。滑动窗口计数器对于经历稳定流量偶尔突发的 API 是理想的,因为它可以防止在管理峰值负载时突然拒绝。在请求速率可变的 CDN 中也非常有用,可确保有效的内容分发而不会使网络超载。
滑动窗口计数器的局限性:
- 稍微比固定窗口复杂: 虽然不像日志方法那样耗费大量资源,但是它比基本的固定窗口计数器更复杂。
- 高估的可能性: 在某些场景中,由于窗口重叠,可能允许的请求比预期的要多一些。
7 大模型应用中的限速特点和应对
如果在大模型应用中收到HTTP状态码429错误,说明我们受到了大模型API的限速约束。例如,Azure OpenAI 对“每分钟令牌”(TPM)和“每分钟请求”(RPM)施加了限制。理解和管理这些限制对于保持平稳运行和避免中断非常重要。
7.1 与大模型限速相关的基本概念
了解限速的原因,需要回顾一些大模型应用中的基本概念(以Azure OpenAI 为例)。
- 令牌(token): OpenAI 模型处理的文本单元,用于测量输入和输出文本,影响使用和计。英语中的1个token≈4个字符。不同的 OpenAI 模型有不同的令牌输入限制,如 GPT-3.5 Turbo、 GPT-4等。
- 配额(quota): 这些是 OpenAI API 用户在特定时间范围内可以使用的请求、令牌或计算资源的最大数量。
- TPM (每分钟的token数量) : 基于请求在接收时被请求处理的token计数的速率限制。这对于速率限制是至关重要的,但是不同于计费所使用的计数,计数是在处理后计算出来的。
- RPM (每分钟的请求数) : RPM 依赖于 TPM,每1000 TPM 的转换为6 RPM。
- 计费模型:有两种——在PAYG (Pay-As-You-Go)这种模式下,用户是根据实际使用情况收费的,它具有灵活性,并且对于不同的工作负载具有成本效益;PTU (规定吞吐量单元) :这种预付费模式为用户分配一定级别的容量,非常适合可预测的大容量使用。
如果大模型应用需要大的令牌或高完成令牌,即使不能满足 RPM,服务器也会节流。如果工作负载需要短时间的完成或提示,但是需要大量的 API 请求,那么服务将会节流。TPM 评估因素如下:
- 提示文本: 提示中发送的令牌已知数量。
- Max_Tokens: 令牌数量的约束,较高的值可能导致错误代码429。
- Best_of: 需要从 LLM 得到的答案数量。
7.2 限速的预期计算
假设TPM 配额为 每分钟100,000个token,RPM 配额为每分钟600个请求(基于每1000 TPM约为 6 RPM 的转换度量),那么
(1)对于大量使用token的场景:
应用程序处理大型文档,每个请求需要大量token。如果每个请求使用大约1,000个token,使用假设中TPM 配额,则最多可以每分钟发出100个请求(100,000个token/每个请求1,000个token)。如果应用程序试图在前10秒内处理所有100个请求,服务器将限制请求,从而导致 HTTP 429错误。这是因为速率限制是在较短的时间(1或10秒)内计算的,以确保均匀分布。
(2) 对于大量请求的场景:
应用程序处理简短的提示,每个请求所需的token较少,每个请求使用大约100个token。如果 TPM 配额为100,000,那么每分钟最多可以发出1,000个请求(每个请求100,000个令牌)。尽管请求的数量很多,但 RPM 配额将限制为每分钟600个请求[每1000 TPM 为6 RPM ]。如果应用程序超过了这个限制,即使令牌的总使用量在 TPM 配额之内,服务器也会限制请求。
7.3 限速的应对
面向大模型API 的限速,一般的应对方法如下:
- 设置“ max_tokens”和“ best_of”参数为较小值。如果预期响应较小,则避免使用较大的 max _ tokens 值。
- 配额管理: 针对高流量部署增加 TPM,针对有限的需求减少 TPM。
- 实现重试逻辑: 确保 LLM 应用程序能够处理重试。
- 流量逐渐增加: 避免工作量的剧烈变化,逐渐增加。
而且,我们可以使用类似 LangChain 的 SDK 在客户端级别实现负载平衡。这种方法将 API 请求分布在多个客户机上,减少了达到速率限制的可能性。另外,使用 Azure API 管理(APIM)创建自定义策略,以更有效地管理和分配负载。您可以在这里了解如何使用 APIM 实现负载均衡。
8. 小结
在快节奏的 API 世界中,速率限制就像节奏设定器一样,确保一切顺利而有效地运行。关键在于选择正确的方法,无论是固定窗口的一致性、滑动窗口日子的精度,还是滑动计数器的平衡,简单而有效,正确的速率限制策略是一个顺利的数字体验的关键,保持服务快速可靠,并为未来做好准备。同样, 我们在大模型应用中要完善对API限速的应对。