关于前端:通过Node和Redis进行API速率限制

62次阅读

共计 2849 个字符,预计需要花费 8 分钟才能阅读完成。

速率限度能够爱护和进步基于 API 的服务的可用性。如果你正在与一个 API 对话,并收到 HTTP 429 Too Many Requests 的响应状态码,阐明你曾经被速率限度了。这意味着你超出了给定工夫内容许的申请数量。你须要做的就是加快脚步,稍等片刻,而后再试一次。

为什么要速率限度?

当你思考限度你本人的基于 API 的服务时,你须要在用户体验、安全性和性能之间进行衡量。

管制数据流的最常见起因是放弃基于 API 的服务的可用性。但也有平安方面的益处,一次无心或无意的入站流量激增,就会占用贵重的资源,影响其余用户的可用性。

通过管制传入申请的速率,你能够:

  • 保障服务和资源不被“吞没”。
  • 弛缓暴力攻打
  • 避免分布式拒绝服务(DDOS)攻打

如何施行限速?

速率限度能够在客户端级别,应用程序级别,基础架构级别或介于两者之间的任何地位实现。有几种办法能够管制 API 服务的入站流量:

  • 按用户:跟踪用户应用 API 密钥、拜访令牌或 IP 地址进行的调用
  • 按天文区域划分:例如升高每个天文区域在一天的顶峰时段的速率限度
  • 按服务器:如果你有多个服务器解决对 API 的不同调用,你可能会对拜访更低廉的资源施行更严格的速率限度。

你能够应用这些速率限度中的任何一种(甚至组合应用)。

无论你抉择如何实现,速率限度的指标都是建设一个检查点,该检查点回绝或通过拜访你的资源的申请。许多编程语言和框架都有实现这一点的内置性能或中间件,还有各种速率限度算法的选项。

这是应用 Node 和 Redis 制作本人的速率限制器的一种办法:

  1. 创立一个 Node 利用
  2. 应用 Redis 增加速率限制器
  3. 在 Postman 中测试

???? 在 GitHub 上查看代码示例。

在开始之前,请确保已在计算机上安装了 Node 和 Redis。

步骤 1:建设 Node 应用程序

从命令行设置一个新的 Node 利用。通过 CLI 提醒,或增加 —yes 标记来承受默认选项。

$ npm init --yes

如果在我的项目设置过程中承受了默认选项,则为入口点创立一个名为 index.js 的文件。

$ touch index.js

装置 Express Web 框架,而后在 index.js 中初始化服务器。

const express = require('express')
const app = express()
const port = process.env.PORT || 3000

app.get('/', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))

从命令行启动服务器。

$ node index.js

回到 index.js 中,创立一个路由,先查看速率限度,如果用户没有超过限度再容许拜访资源。

app.post('/', async (req, res) => {async function isOverLimit(ip) {// to define}
  // 查看率限度
  let overLimit = await isOverLimit(req.ip)
  if (overLimit) {res.status(429).send('Too many requests - try again later')
    return
  }
  // 容许拜访资源
  res.send("Accessed the precious resources!")
})

在下一步中,咱们将定义速率限制器函数 isOverLimit

步骤 2:应用 Redis 增加速率限制器

Redis 是一个内存中键值数据库,因而它能够十分疾速地检索数据。应用 Redis 施行速率限度也非常简单。

  • 存储一个像用户 IP 地址一样的 key。
  • 减少从该 IP 收回的调用数量
  • 在指定时间段后使记录过期

下图所示的限速算法是一个 滑动窗口计数器 的例子。一个用户如果提交的调用数量适中,或者随着工夫的推移将它们分隔开,就永远不会达到速率限度。超过 10 秒窗口内最大申请的用户必须期待足够的工夫来复原其申请。

从命令行为 Node 装置一个名为 ioredis 的 Redis 客户端。

$ npm install ioredis

在本地启动 Redis 服务器。

$ redis-server

而后在 index.js 中要求并初始化 Redis 客户端。

const redis = require('ioredis')
const client = redis.createClient({
  port: process.env.REDIS_PORT || 6379,
  host: process.env.REDIS_HOST || 'localhost',
})
client.on('connect', function () {console.log('connected');
});

定义咱们上一步开始写的 isOverLimit 函数,依照 Redis 的这个模式,依照 IP 来保留一个计数器。

async function isOverLimit(ip) {
  let res
  try {res = await client.incr(ip)
  } catch (err) {console.error('isOverLimit: could not increment key')
    throw err
  }
  console.log(`${ip} has value: ${res}`)
  if (res > 10) {return true}
  client.expire(ip, 10)
}

这就是速率限制器。

当用户调用 API 时,咱们会查看 Redis 以查看该用户是否超出限度。如果是这样,API 将立刻返回 HTTP 429 状态代码,并显示音讯 Too many requests — try again later。如果用户在限度之内,咱们将继续执行下一个代码块,在该代码块中,咱们能够容许拜访受爱护的资源(例如数据库)。

在进行速率限度查看期间,咱们在 Redis 中找到用户的记录,并减少其申请计数,如果 Redis 中没有该用户的记录,那么咱们将创立一个新记录。最初,每条记录将在最近一次流动的 10 秒内过期。

在下一步中,请确保咱们的限速器失常运行。

步骤 3:在 Postman 中进行测试

保留更改,而后重新启动服务器。咱们将应用 Postman 将 POST 申请发送到咱们的 API 服务器,该服务器在本地运行,网址为 http:// localhost:3000

持续疾速间断发送申请以达到你的速率限度。

对于限速的最终想法

这是 Node 和 Redis 的速率限制器的简略示例,这只是开始。有一堆策略和工具能够用来架构和实现你的速率限度。而且还有其余的加强性能能够通过这个例子来摸索,比方:

  • 在响应注释或作为 Retry-after 标头中,让用户晓得在重试之前应该期待多少工夫
  • 记录达到速率限度的申请,以理解用户行为并正告歹意攻打
  • 尝试应用其余速率限度算法或其余中间件

请记住,当你钻研 API 限度时,你是在性能、安全性和用户体验之间进行衡量。你现实的速率限度解决方案将随着工夫的推移而扭转,同时也会思考到这些因素。


最近整顿了一份优质视频教程资源,想要的关注公众号即可取得。

正文完
 0