限流是一个流行的分布式系统模式。它是所有现代大规模应用不可或缺的一部分。它控制用户或服务访问资源(如 API、服务或网络)的速率。它在保护系统资源和确保所有用户公平使用方面发挥着关键作用。
在本系列中,我们将深入探讨限流。我们将讨论限流如何在现代应用中使用,并检查流行的限流算法。我们将深入探讨生产级限流器的关键设计考虑因素和实现策略。最后我们将介绍一些真实世界的案例研究和最佳实践。
什么是限流
限流控制用户或服务访问资源的速率。当请求速率超过限流器定义的阈值时,请求会被限制或阻止。以下是一些例子:
- 用户每秒发送消息不超过 2 条
- 一个 IP 地址每天最多创建 10 个账户
- 同一设备每周领取奖励不超过 5 次

限流是现代大规模应用不可或缺的一部分。让我们看看限流器的一些好处。虽然我们这里关注 API 限流器,但这些好处通常适用于为其他用例部署的限流器。
防止资源枯竭:限流有助于防止拒绝服务(DoS)攻击导致的资源枯竭。几乎所有大型科技公司发布的 API 都强制执行某种形式的限流。例如,Twitter 将推文数量限制为每 3 小时 300 条。Google Docs API 将读取请求限制为每用户每 60 秒 300 次。限流器通过拒绝超额调用来防止 DoS 攻击(无论是有意的还是无意的)。
控制成本超支:限流可以帮助防止过度使用资源导致的成本超支。如果资源被大量请求过载,可能需要额外的资源或容量来处理负载,这会产生额外成本。
** outbound 请求控制**:限流对于发出出站请求的服务也至关重要,特别是那些使用付费第三方 API 的服务。许多第三方服务对其外部 API 按调用次数收费。一些例子是检查信用、进行付款、检索健康记录等服务。限制调用次数对控制成本至关重要。
负载平衡:虽然限流对防止 DoS 攻击至关重要,但它在一般负载平衡和服务质量维护方面也发挥着关键作用。高容量请求(不仅来自恶意来源,也来自重度使用)会使服务器负担过重。
为了减少服务器负载,限流器用于在请求生命周期早期拒绝恶意机器人或重度用户发出的多余请求。

限流的应用场景
限流可用于各种情况以有效管理资源。做好后,它可以防止滥用并确保公平使用。
用户级限流:限流通常在用户级应用。考虑一个流行的社交媒体平台,用户频繁发布内容和评论。为了防止垃圾邮件或恶意机器人活动,平台可能会强制执行用户级限流。它限制用户在一小时内可以发布的帖子或评论数量。
应用级限流:限流也可以应用级应用。一个例子是在线票务平台。在大型音乐会销售当天,平台可以预期流量大幅增加。应用级限流在这种情况下非常有用。它限制每分钟购票总数。这种做法保护系统不被压垮,并确保每个人都有公平的机会尝试获得门票。
API 级限流:API 级限流也很常见。考虑一个云存储服务,提供上传和下载文件的 API。为了确保公平使用并保护系统免受滥用,服务可能会强制执行每个用户每分钟可以进行的 API 调用次数限制。
账户级别限流:限流也可以基于用户账户级别应用。提供多层服务的 SaaS 平台可以对每层有不同的使用限制。免费层用户可能有比较高级用户更低的限流。这有效管理资源使用,同时鼓励用户升级到更高层以获取更高限制。
这些只是一些例子。它们展示了限流策略如何在不同场景和服务中部署。
核心概念
大多数限流实现共享三个核心概念。它们是限制、窗口和标识符。
限制(Limit)定义了指定时间跨度内允许的请求或操作的上限。例如,我们可能允许用户每小时发送不超过 100 条消息。
窗口(Window)是限制生效的时间段。它可以是任何长度的时间,无论是一小时、一天还是一周。较长的持续时间确实有自己的实现挑战,比如存储持久性,我们稍后会讨论。
标识符(Identifier)是区分各个调用者的唯一属性。用户 ID 或 IP 地址是常见例子。

另一个需要理解的核心概念是不同类型的限流响应。它们通常分为三类:阻止、节流和整形。
阻止(Blocking)发生在超过限制的请求被拒绝访问资源时。通常表示为错误消息,如 HTTP 状态码 429(Too Many Requests)。
节流(Throttling)涉及减慢或延迟超出限制的请求。一个例子是视频流服务为超过数据上限的用户降低流质量。
整形(Shaping)允许超出限制的请求。但这些请求被分配较低的优先级。这确保遵守限制的用户获得优质服务。例如,在内容分发网络中,超过限制的用户的请求可能被最后处理,而普通用户的请求被优先处理。

这些基本核心概念为深入探讨各种常见限流算法奠定了基础。
常见限流算法
限流可以使用不同的算法实现。它们各有独特的优缺点。我们深入探讨一些常见的限流算法。我们将涵盖:
- 固定窗口计数器
- 滑动窗口日志
- 滑动窗口计数器
- 令牌桶
- 漏桶
固定窗口计数器
固定窗口计数器算法将时间线划分为固定大小的时间窗口,并为每个窗口分配一个计数器。每个请求根据请求的相对成本将计数器增加某个值。一旦计数器达到阈值,后续请求会被阻止,直到新的时间窗口开始。
让我们用一个具体例子看看它是如何工作的。在这个例子中,时间单位是 1 秒,系统允许每秒最多 3 个请求。在每个 1 秒时间窗口中,如果收到超过 3 个请求,同一时间窗口内到达的后续请求会被丢弃。

本文为学习目的的个人翻译,译文仅供参考。
原文链接:Rate Limiting Fundamentals。
版权归原作者或原刊登方所有。本文为非官方译本;如有不妥,请联系删除。