在开发 api 网关的时,做过一些简单的限流,比如说静态拦截和动态拦截;静态拦截说白了就是限流某一个接口在一定时间窗口的请求数。用户可以在系统上给他们的接口配置一个每秒最大调用量,如果超过这个限制,则拒绝服务此接口,而动态拦截其实也是基于静态拦截进行改进,我们可以依据当前系统的响应时间来动态调整限流的阈值,如果响应较快则可以把阈值调的大一些,放过更多请求,反之则自动降低限流阈值,只使少量请求通过。
location /hello { access_by_lua_block { local limit_count = require"resty.limit.count"
-- rate: 10/min local lim, err = limit_count.new("my_limit_count_store", 120, 60) ifnot lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.count object: ", err) return ngx.exit(500) end
local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) -- 如果请求数在限制范围内,则当前请求被处理的延迟(这种场景下始终为0,因为要么被处理要么被拒绝)和将被处理的请求的剩余数 ifnot delay then if err == "rejected"then return ngx.exit(503) end
ngx.log(ngx.ERR, "failed to limit count: ", err) return ngx.exit(500) end }
location /hello { access_by_lua_block { local limit_req = require "resty.limit.req" -- 这里设置rate=2/s,漏桶桶容量设置为0,(也就是来多少水就留多少水) -- 因为resty.limit.req代码中控制粒度为毫秒级别,所以可以做到毫秒级别的平滑处理 local lim, err = limit_req.new("my_limit_req_store", 2, 0) if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end
local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) if not delay then iferr == "rejected" then return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end }
location /hello { access_by_lua_block { local limit_req = require"resty.limit.req" -- 这里设置rate=2/s,漏桶桶容量设置为0,(也就是来多少水就留多少水) -- 因为resty.limit.req代码中控制粒度为毫秒级别,所以可以做到毫秒级别的平滑处理 local lim, err = limit_req.new("my_limit_req_store", 2, 60) ifnot lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end
local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) ifnot delay then if err == "rejected"then return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end -- 此方法返回,当前请求需要delay秒后才会被处理,和他前面对请求数 -- 所以此处对桶中请求进行延时处理,让其排队等待,就是应用了漏桶算法 -- 此处也是与令牌桶的主要区别既 if delay >= 0.001then ngx.sleep(delay) end }
location /hello { access_by_lua_block { local limit_req = require"resty.limit.req"
local lim, err = limit_req.new("my_limit_req_store", 2, 0) ifnot lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end
local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) ifnot delay then if err == "rejected"then return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end -- 此方法返回,当前请求需要delay秒后才会被处理,和他前面对请求数 -- 此处忽略桶中请求所需要的延时处理,让其直接返送到后端服务器, -- 其实这就是允许桶中请求作为突发流量 也就是令牌桶桶的原理所在 if delay >= 0.001then -- ngx.sleep(delay) end }