每个公共API最终都面临虐待。
它可能是恶意的脚本敲打你的端点, 错误的配置客户端在循环中重试, 或者只是突然的流量激增。
在不限制速率的情况下,你的后端可能会被压倒,导致反应缓慢或崩溃.
利率限制保护您的服务,保持成本的可预见性,并确保所有消费者公平使用。
我记得我的第一个制作事件:一个客户意外地将每秒数千个请求发送到一个搜索终点.
数据库CPU被提升到100%,整个应用在几分钟内变得无响应.
简单的费率限制将完全防止这种情况。
什么是限制利率?
速率限制控制客户端在特定时间窗口内可以提出多少请求.
这是一个政策,定义了阈值和超过阈值时的动作.
共同行动包括拒绝或拖延请求。
主要概念有: 限制:允许在窗口中的最大请求(例如每分钟100个请求).
窗口 : 时限(如1分1小时).
标识人:谁受到限制?
通常是一个IP地址,API密钥,或用户ID.
简单固定窗口算法 最简单的方法是固定窗口。
您在时间桶中跟踪每个标识符的请求 。
例如,允许每分钟提出10个请求。
当一个请求出现时,您会增加当前时刻的计数器。
如果计数器超过10,拒绝.
以下是在Node.js中使用内映图的最小执行: 这对简单案件有效,但有一个缺陷:一个客户端可以在一窗口的一端和下个窗口的一端爆裂,有效将率翻一番.
例如以59秒请求10个,再以61秒请求10个.
滑动窗口日志 A 更精确的方法是滑动窗口日志.
您存储每个请求的时间戳, 并计算有多少属于最后一个 。
这避免了爆出的问题,但使用了更多的记忆.
这是比较精确的,但如果清单变得庞大,可能会缓慢。
对于高流量的API, 你会想要一个更有效率的结构 像一个象征性的桶。
Token Bucket 算法 标志桶很受欢迎,因为它允许在平滑出长期速率的同时出击.
想想一个能维持信号的桶 每个请求都消耗一个符号.
托肯斯以固定的费率(例如每秒1个令牌)加入.
如果桶是空的,则请求被拒绝.
这里有一个简单的执行: 这允许客户端立即提出10个请求,然后每秒提出1个请求.
反应能力与保护能力之间保持了良好的平衡.
现实世界的考虑 在生产中,你很少写自己的限速器.
类似Node的图书馆,或者像Redis基于限制器(例如.)的服务处理分布式情景.
但了解基本知识有助于你选择正确的基础。
需要考虑的要点: 分布式系统:内映图无法跨多例工作.
使用类似Redis的有原子操作的共享商店.
正确识别客户端:IP地址可以共享(NAT,代理).
在可用时优先使用 API 密钥或用户ID 。
回应信头:包含, 并让客户知道如何行为。 graceful records:当一个极限被击中时,用头返回一个明显的错误,以便客户端可以退后.
测试您的速率限制器总是写测试 。
对于一个简单的受限者,测试:在受限通行证内请求.
超过限额的要求是429 窗口重排正确 。
以下是使用节点内置测试跑道的快速测试: Final Thoughts Reservation是任何API开发者的基本工具.
以简单的固定窗口开始,如果你是原型的,但为了制作,考虑一个象征性的桶或者一个经过战斗测试的库.
最重要的部分是故意的:知道你的限度,记录这些限度,在客户方面也优雅地处理429个。
你未来的自我,你的用户, 将会感谢您 当不可避免的交通高峰 没有削减你的服务.