JavaScript中的请求限制:如何防止API崩溃

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

JavaScript中的速率限制与节流:保护与性能

\n\n

您是否曾想过,为什么在快速点击“发送”按钮几十次后,您最喜爱的服务突然停止响应?或者为什么有些网站会要求您在重新提交表单前“等待30秒”?答案在于两种强大的机制,它们能防止后端过载,并保护用户免受“错误”的困扰:速率限制和节流。

\n\n

在本文中,我们将探讨如何在纯JavaScript和Node.js中应用这些技术。您将了解节流与防抖的区别,如何为API编写一个简单的速率限制器,以及为什么您的网站会运行得更快。让我们开始吧!

\n\n

什么是速率限制,为什么需要它?

\n\n

速率限制是一种保护机制,用于限制客户端(或IP地址)在特定时间段内的请求数量。想象一个道闸:汽车可以通行,但每10秒只能通过一次。

\n\n

它应用在哪些场景?

\n
    \n
  • 保护API免受DDoS攻击和垃圾信息。
  • \n
  • 防止大量请求导致服务器过载。
  • \n
  • 控制付费API的资源使用(例如,每小时100次请求)。
  • \n
  • 防止客户端出现“无限循环”错误。
  • \n
\n\n

与平滑请求流的节流不同,速率限制是一道硬性屏障:“停止,您已超出限制”。

\n\n

节流 vs 防抖:主要区别

\n\n

人们经常混淆节流和防抖。让我们来理清概念。

\n\n
    \n
  • 节流 — 确保函数在N毫秒内最多被调用一次。想象一个水龙头:您打开它,即使您更快地转动把手,水也会以恒定速度流出。
  • \n
  • 防抖 — 将函数调用推迟到最后一个事件发生后N毫秒。非常适合自动补全搜索:当用户输入时,不会发送请求。
  • \n
\n\n

在速率限制的上下文中,我们关注的是节流——我们希望控制频率,而不是推迟请求。

\n\n

最简单的JavaScript速率限制器

\n\n

让我们在Node.js上编写自己的速率限制器实现。它会记住每个用户上次请求的时间,并阻止过于频繁的访问。

\n\n
class RateLimiter {\n  constructor(limit, windowMs) {\n    this.limit = limit;          // 最大请求数\n    this.windowMs = windowMs;    // 时间窗口(毫秒)\n    this.requests = new Map();   // 存储:userId -> [timestamps]\n  }\n\n  allow(userId) {\n    const now = Date.now();\n    const userRequests = this.requests.get(userId) || [];\n    \n    // 删除过期的记录\n    const recentRequests = userRequests.filter(\n      ts => now - ts < this.windowMs\n    );\n    \n    if (recentRequests.length >= this.limit) {\n      console.log(`用户 ${userId} 超出速率限制`);\n      return false;\n    }\n    \n    recentRequests.push(now);\n    this.requests.set(userId, recentRequests);\n    return true;\n  }\n}\n\n// 使用示例\nconst limiter = new RateLimiter(5, 60000); // 每分钟5次请求\n\n// 模拟请求\nfor (let i = 0; i < 10; i++) {\n  setTimeout(() => {\n    const allowed = limiter.allow('user123');\n    console.log(`请求 ${i+1}: ${allowed ? '✅ 允许' : '❌ 阻止'}`);\n  }, i * 2000); // 每2秒一次\n}
\n\n

这段代码非常适合教学目的,但在生产环境中,最好使用现成的解决方案(例如,用于Express的express-rate-limit或rate-limiter-flexible)。

\n\n

客户端节流:防止快速点击

\n\n

问题通常出现在客户端:用户多次点击“发送”按钮,导致请求并行发出。R

博客

书籍推荐