什么时候应该在代码中实施限制?
对于大型项目,通常最好使用 Cloudflare Rate Limiting 或 HAProxy 等工具。这些功能强大、可靠,可以为您处理繁重的工作。
但是对于较小的项目 - 或者如果您想了解事情是如何工作的 - 您可以在代码中创建自己的速率限制器。为什么?
- 很简单:您将构建一些简单易懂的东西。
- 预算友好:除了托管服务器之外,无需额外费用。
- 它适用于小型项目:只要流量较低,它就能保持快速高效。
- 它是可重用的:您可以将其复制到其他项目中,而无需设置新的工具或服务。
你将学到什么
在本指南结束时,您将了解如何在 TypeScript 中构建基本节流器以保护您的 API 不被淹没。以下是我们将介绍的内容:
- 可配置的时间限制:每次被阻止的尝试都会增加锁定持续时间以防止滥用。
- 请求上限:设置允许的最大请求数。这对于涉及付费服务的 API 尤其有用,例如 OpenAI。
- 内存存储:一种无需 Redis 等外部工具即可工作的简单解决方案,非常适合小型项目或原型。
- 每用户限制:使用 IPv4 地址跟踪每个用户的请求。我们将利用 SvelteKit 的内置方法轻松检索客户端 IP。
本指南旨在作为一个实用的起点,非常适合想要学习基础知识而又不想不必要的复杂性的开发人员。 但它还没有准备好生产。
在开始之前,我想对 Lucia 的速率限制部分给予正确的评价。
节流器实施
让我们定义 Throttler 类:
export class Throttler { private storage = new Map<string throttlingcounter>(); constructor(private timeoutSeconds: number[]) {} } </string>
Throttler 构造函数接受超时持续时间 (timeoutSeconds) 列表。每次用户被阻止时,持续时间都会根据此列表逐渐增加。最终,当达到最终超时时,您甚至可以触发回调以永久禁止用户的 IP - 尽管这超出了本指南的范围。
以下是创建阻止用户增加间隔的节流器实例的示例:
const throttler = new Throttler([1, 2, 4, 8, 16]);
此实例第一次会阻止用户一秒钟。两人第二次,以此类推。
我们使用 Map 来存储 IP 地址及其相应的数据。地图是理想的选择,因为它可以有效地处理频繁的添加和删除。
专业提示:使用地图来处理经常变化的动态数据。对于静态、不变的数据,对象更好。 (兔子洞1)
当您的端点收到请求时,它会提取用户的 IP 地址并咨询 Throttler 以确定是否应允许该请求。
它是如何运作的
-
案例 A:新用户或不活跃用户
如果在 Throttler 中找不到该 IP,则这可能是用户的第一个请求,或者他们已经处于不活动状态足够长的时间。在这种情况下:- 允许该操作。
- 通过存储用户的 IP 并设置初始超时来跟踪用户。
-
案例 B:活跃用户
如果找到该IP,则说明该用户之前曾发出过请求。这里:- 检查自上一个块以来是否已经过了所需的等待时间(基于 timeoutSeconds 数组)。
- 如果已经过去了足够的时间:
- 更新时间戳。
- 增加超时索引(上限为最后一个索引以防止溢出)。
- 如果没有,请拒绝该请求。
在后一种情况下,我们需要检查自上一个区块以来是否已经过去了足够的时间。通过索引,我们知道应该引用哪个 timeoutSeconds。如果没有,只需反弹即可。否则更新时间戳。
export class Throttler { private storage = new Map<string throttlingcounter>(); constructor(private timeoutSeconds: number[]) {} } </string>
更新索引时,上限为timeoutSeconds的最后一个索引。如果没有它,counter.index 1 就会溢出,接下来访问 this.timeoutSeconds[counter.index] 将导致运行时错误。
端点示例
此示例展示了如何使用 Throttler 来限制用户调用 API 的频率。如果用户发出太多请求,他们会收到错误,而不是运行主逻辑。
const throttler = new Throttler([1, 2, 4, 8, 16]);
认证注意事项
在登录系统中使用速率限制时,您可能会遇到以下问题:
- 用户登录,触发 Throttler 将超时与其 IP 关联起来。
- 用户注销或会话结束(例如,立即注销、cookie 随会话过期以及浏览器崩溃等)。
- 当他们不久后尝试再次登录时,Throtler 可能仍会阻止他们,返回 429 Too Many Requests 错误。
为了防止这种情况,请使用用户的唯一用户ID而不是他们的IP进行速率限制。此外,您必须在成功登录后重置节流器状态,以避免不必要的阻塞。
在 Throttler 类中添加重置方法:
export class Throttler { // ... public consume(key: string): boolean { const counter = this.storage.get(key) ?? null; const now = Date.now(); // Case A if (counter === null) { // At next request, will be found. // The index 0 of [1, 2, 4, 8, 16] returns 1. // That's the amount of seconds it will have to wait. this.storage.set(key, { index: 0, updatedAt: now }); return true; // allowed } // Case B const timeoutMs = this.timeoutSeconds[counter.index] * 1000; const allowed = now - counter.updatedAt >= timeoutMs; if (!allowed) { return false; // denied } // Allow the call, but increment timeout for following requests. counter.updatedAt = now; counter.index = Math.min(counter.index + 1, this.timeoutSeconds.length - 1); this.storage.set(key, counter); return true; // allowed } }
登录成功后使用:
export class Throttler { private storage = new Map<string throttlingcounter>(); constructor(private timeoutSeconds: number[]) {} } </string>
通过定期清理来管理过时的 IP 记录
当您的节流器跟踪 IP 和速率限制时,重要的是要考虑如何以及何时删除不再需要的 IP 记录。如果没有清理机制,您的节流器将继续在内存中存储记录,随着数据的增长,可能会导致性能问题。
为了防止这种情况,您可以实现一个清理功能,在一定时间不活动后定期删除旧记录。以下是如何添加简单的清理方法以从节流器中删除过时条目的示例。
const throttler = new Throttler([1, 2, 4, 8, 16]);
安排清理的一个非常简单的方法(但可能不是最好的)是使用 setInterval:
export class Throttler { // ... public consume(key: string): boolean { const counter = this.storage.get(key) ?? null; const now = Date.now(); // Case A if (counter === null) { // At next request, will be found. // The index 0 of [1, 2, 4, 8, 16] returns 1. // That's the amount of seconds it will have to wait. this.storage.set(key, { index: 0, updatedAt: now }); return true; // allowed } // Case B const timeoutMs = this.timeoutSeconds[counter.index] * 1000; const allowed = now - counter.updatedAt >= timeoutMs; if (!allowed) { return false; // denied } // Allow the call, but increment timeout for following requests. counter.updatedAt = now; counter.index = Math.min(counter.index + 1, this.timeoutSeconds.length - 1); this.storage.set(key, counter); return true; // allowed } }
这种清理机制有助于确保您的节流器不会无限期地保留旧记录,从而保持应用程序的高效。虽然这种方法简单且易于实现,但可能需要针对更复杂的用例进一步细化(例如,使用更高级的调度或处理高并发)。
通过定期清理,您可以防止内存膨胀,并确保一段时间内未尝试发出请求的用户不再被跟踪 - 这是使您的速率限制系统可扩展且资源高效的第一步。
-
如果您喜欢冒险,您可能有兴趣阅读属性的分配方式及其变化方式。另外,为什么不考虑诸如内联缓存之类的虚拟机优化,单态性特别青睐这种优化。享受。 ↩
以上是节流解释:管理 API 请求限制的指南的详细内容。更多信息请关注PHP中文网其他相关文章!

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

记事本++7.3.1
好用且免费的代码编辑器

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境