今天简单解释下令牌桶法,系统会以一定的速率往桶里添加令牌,处理请求前,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则返回失败。
大概描述如下:
所有的请求在处理之前都需要拿到一个可用的令牌才会被处理; 获取不到令牌,则请求返回失败 根据限流大小,设置按照一定的速率往桶里添加令牌; 桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
实现关键点:
- 初始化固定数量的令牌放入令牌桶中
- 初始化和开启一个定时的任务,定时往令牌桶添加令牌
- 提供一个获取令牌的方法,获取一个令牌,令牌桶中减一,如果令牌桶中为空,返回失败
class TokenLimiter {
constructor(limit) {
this.limit = limit
this.arrayQueue = []
this.init()
this.start()
}
//初始化令牌数量
init() {
console.log(1)
for (let i = 0; i < this.limit; i++) {
this.arrayQueue.push('1')
}
}
//获取令牌
getToken() {
return !!this.arrayQueue.shift()
}
//开启一个定时器在特定的时间初始化令牌
start() {
setInterval(() => {
if (this.arrayQueue.length === 0) {
console.log(`令牌没有了,正在补充。。。。。`)
this.init()
}
},1000)
}
}
module.exports = TokenLimiter
那么我们如何在Koa中使用它呢!如下:
const Koa = require('koa')
const Router = require('koa-router')
const moment = require('moment')
const TokenLimiter = require('./tokenLimiter')
const router = new Router()
const app = new Koa()
//实例化TokenLimiter类,传入你初始化的令牌数
const tokenLimiter = new TokenLimiter(10)
const data = require('./data.json')
const limitWrapper = async (ctx, next) => {
const flag = tokenLimiter.getToken()
if (!flag) {
ctx.response.body = '网络错误'
ctx.response.status = 500
}
await next()
}
app.use(limitWrapper)
const leaderboard = async (ctx) => {
const { type, dateType } = ctx.query
const filterDate = (date) => moment(moment().subtract(dateType === 'd' ? 0 : 1, dateType).format('YYYY-MM-DD')).isSameOrBefore(date)
ctx.response.body = data.filter(x => x.type === type && filterDate(x.date))
}
router.get('/leaderboard', leaderboard)
app.use(router.routes())
app.listen(3009)
以上就是如何在Koa实现节流思路,看完后觉得还行,给个赞哦。
还有本人有丰富的AWS Lambda使用经验,有对这方面感兴趣的小伙伴们可以探讨下