limit-req 漏桶算法限速插件
关键属性
源码实现
local function create_limit_obj(conf)
core.log.info("create new limit-req plugin instance")
return limit_req_new("plugin-limit-req", conf.rate, conf.burst)
end
function _M.access(conf, ctx)
local lim, err = core.lrucache.plugin_ctx(lrucache, ctx, nil,
create_limit_obj, conf)
if not lim then
core.log.error("failed to instantiate a resty.limit.req object: ", err)
if conf.allow_degradation then
return
end
return 500
end
local key
if conf.key == "consumer_name" then
if not ctx.consumer_name then
core.log.error("consumer not found.")
return 500, { message = "Consumer not found."}
end
key = ctx.consumer_name .. ctx.conf_type .. ctx.conf_version
else
key = (ctx.var[conf.key] or "") .. ctx.conf_type .. ctx.conf_version
end
core.log.info("limit key: ", key)
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
if conf.rejected_msg then
return conf.rejected_code, { error_msg = conf.rejected_msg }
end
return conf.rejected_code
end
core.log.error("failed to limit req: ", err)
if conf.allow_degradation then
return
end
return 500
end
if delay >= 0.001 and not conf.nodelay then
sleep(delay)
end
end
使用Openresty中的resty.limit.req模块
静态拦截就是限流某一个接口在一定时间单位的请求数。一般就是单位1s内的客户端的请求数。
平滑限制请求数
limit_req_new("plugin-limit-req", 10, 0)
– 这里设置rate=10/s,漏桶桶容量设置为0,(也就是来多少水就留多少水)
– 因为resty.limit.req代码中控制粒度为毫秒级别,所以可以做到毫秒级别的平滑处理
漏桶算法限流
limit_req_new("plugin-limit-req", 10, 10)
...
-- 超过20的部分直接拒接
-- 超过10,低于20的部分,放入桶中进行延时处理,让其排队等待,就是应用了漏桶算法
if delay >= 0.001 and not conf.nodelay then
sleep(delay)
end
令牌桶算法限流
limit_req_new("plugin-limit-req", 10, 10)
...
-- 如果 nodelay 为 true, 请求速率超过 rate 但没有超过
--(rate + burst)的请求不会加上延迟, 如果是 false,则
-- 会加上延迟。
if delay >= 0.001 and not conf.nodelay then
-- 若忽略,桶中剩余请求所需要的延时处理,让其直接发送到后端服务器,
-- 其实这就是允许桶中请求作为突发流量直接到后端,这也就是令牌桶的原理所在
sleep(delay)
end