溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

通過Node+Redi如何實現(xiàn)API速率限制

發(fā)布時間:2020-09-21 09:37:38 來源:億速云 閱讀:127 作者:小新 欄目:web開發(fā)

通過Node+Redi如何實現(xiàn)API速率限制?這個問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家?guī)淼膮⒖純?nèi)容,讓我們一起來看看吧!

速率限制可以保護和提高基于API的服務(wù)的可用性。如果你正在與一個API對話,并收到HTTP 429 Too Many Requests的響應(yīng)狀態(tài)碼,說明你已經(jīng)被速率限制了。

為什么要速率限制?

當(dāng)你考慮限制你自己的基于API的服務(wù)時,你需要在用戶體驗、安全性和性能之間進行權(quán)衡。

通過Node+Redi如何實現(xiàn)API速率限制

控制數(shù)據(jù)流的最常見原因是保持基于API的服務(wù)的可用性。但也有安全方面的好處,一次無意或有意的入站流量激增,就會占用寶貴的資源,影響其他用戶的可用性。

通過控制傳入請求的速率,你可以:

  • 保障服務(wù)和資源不被“淹沒”。
  • 緩和暴力攻擊
  • 防止分布式拒絕服務(wù)(DDOS)攻擊

如何實施限速?

速率限制可以在客戶端級別,應(yīng)用程序級別,基礎(chǔ)架構(gòu)級別或介于兩者之間的任何位置實現(xiàn)。有幾種方法可以控制API服務(wù)的入站流量:

  • 按用戶:跟蹤用戶使用API密鑰、訪問令牌或IP地址進行的調(diào)用
  • 按地理區(qū)域劃分:例如降低每個地理區(qū)域在一天的高峰時段的速率限制
  • 服務(wù)器:如果你有多個服務(wù)器處理對API的不同調(diào)用,你可能會對訪問更昂貴的資源實施更嚴格的速率限制。

你可以使用這些速率限制中的任何一種(甚至組合使用)。

通過Node+Redi如何實現(xiàn)API速率限制

無論你選擇如何實現(xiàn),速率限制的目標(biāo)都是建立一個檢查點,該檢查點拒絕或通過訪問你的資源的請求。許多編程語言和框架都有實現(xiàn)這一點的內(nèi)置功能或中間件,還有各種速率限制算法的選項。

這是使用Node和Redis制作自己的速率限制器的一種方法:

  1. 創(chuàng)建一個Node應(yīng)用
  2. 使用Redis添加速率限制器
  3. 在Postman中測試
在GitHub上查看代碼示例。

在開始之前,請確保已在計算機上安裝了Node和Redis。

步驟1:建立Node應(yīng)用程序

從命令行設(shè)置一個新的Node應(yīng)用。通過CLI提示,或添加 —yes 標(biāo)志來接受默認選項。

$ npm init --yes

如果在項目設(shè)置過程中接受了默認選項,則為入口點創(chuàng)建一個名為 index.js 的文件。

$ touch index.js

安裝Express Web框架,然后在 index.js 中初始化服務(wù)器。

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}`))

從命令行啟動服務(wù)器。

$ node index.js

回到 index.js 中,創(chuàng)建一個路由,先檢查速率限制,如果用戶沒有超過限制再允許訪問資源。

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!")
})

通過Node+Redi如何實現(xiàn)API速率限制

在下一步中,我們將定義速率限制器函數(shù) isOverLimit

步驟2:使用Redis添加速率限制器

Redis是一個內(nèi)存中鍵值數(shù)據(jù)庫,因此它可以非??焖俚貦z索數(shù)據(jù)。使用Redis實施速率限制也非常簡單。

  • 存儲一個像用戶IP地址一樣的key。
  • 增加從該IP發(fā)出的調(diào)用數(shù)量
  • 在指定時間段后使記錄過期

下圖所示的限速算法是一個滑動窗口計數(shù)器的例子。一個用戶如果提交的調(diào)用數(shù)量適中,或者隨著時間的推移將它們分隔開,就永遠不會達到速率限制。超過10秒窗口內(nèi)最大請求的用戶必須等待足夠的時間來恢復(fù)其請求。

通過Node+Redi如何實現(xiàn)API速率限制

從命令行為Node安裝一個名為ioredis的Redis客戶端。

$ npm install ioredis

在本地啟動Redis服務(wù)器。

$ 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函數(shù),按照Redis的這個模式,按照IP來保存一個計數(shù)器。

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)
}

這就是速率限制器。

當(dāng)用戶調(diào)用API時,我們會檢查Redis以查看該用戶是否超出限制。如果是這樣,API將立即返回HTTP 429狀態(tài)代碼,并顯示消息 Too many requests — try again later 。如果用戶在限制之內(nèi),我們將繼續(xù)執(zhí)行下一個代碼塊,在該代碼塊中,我們可以允許訪問受保護的資源(例如數(shù)據(jù)庫)。

在進行速率限制檢查期間,我們在Redis中找到用戶的記錄,并增加其請求計數(shù),如果Redis中沒有該用戶的記錄,那么我們將創(chuàng)建一個新記錄。最后,每條記錄將在最近一次活動的10秒內(nèi)過期。

在下一步中,請確保我們的限速器正常運行。

步驟3:在Postman中進行測試

保存更改,然后重新啟動服務(wù)器。我們將使用Postman將 POST 請求發(fā)送到我們的API服務(wù)器,該服務(wù)器在本地運行,網(wǎng)址為 http:// localhost:3000。

通過Node+Redi如何實現(xiàn)API速率限制

繼續(xù)快速連續(xù)發(fā)送請求以達到你的速率限制。

通過Node+Redi如何實現(xiàn)API速率限制

感謝各位的閱讀!看完上述內(nèi)容,你們對通過Node+Redi如何實現(xiàn)API速率限制大概了解了嗎?希望文章內(nèi)容對大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI