原文: lua-resty-limit-traffic/lib/resty/limit/count.mdgit
http { lua_shared_dict my_limit_count_store 100m; init_by_lua_block { require "resty.core" } server { location / { access_by_lua_block { local limit_count = require "resty.limit.count" -- rate: 5000 requests per 3600s local lim, err = limit_count.new("my_limit_count_store", 5000, 3600) if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.coutn object: ", err) return ngx.exit(500) end -- use the Authorization header as the limiting key local key = ngx.req.get_headers()["Authorization"] or "public" local delay, err = lim:incoming(key, true) if not delay then if err == "rejected" then ngx.header["X-RateLimit-Limit"] = "5000" ngx.header["X-RateLimit-Remaining"] = 0 return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit count: ", err) return ngx.exit(500) end -- the 2nd return value holds the current remaing number -- of requests for the specified key. local remaining = err ngx.header["X-RateLimit-Limit"] = "5000" ngx.header["X-RateLimit-Remaining"] = remaining } } } }
注: 该模块依赖 lua-resty-core,所以须要:github
init_by_lua_block { require "resty.core" }
syntax: obj, err = class.new(shdict_name, count, time_window)
实例化 class 的对象,该 class 经过 require "resty.limit.count"
返回。ui
该 new 方法携带的参数以下:lua
shdict_name
: lua_shared_dict 声明的共享内存的名称。建议对不一样的限制使用独立的共享内存。count
:指定的请求阈值。time_window
: 请求个数复位前的窗口时间,以秒为单位。local ngx_shared = ngx.shared local setmetatable = setmetatable local assert = assert local _M = { _VERSION = '0.05' } local mt = { __index = _M } -- the "limit" argument controls number of request allowed in a time window. -- time "window" argument controls the time window in seconds. function _M.new(dict_name, limit, window) local dict = ngx_shared[dict_name] if not dict then return nil, "shared dict not found" end assert(limit> 0 and window > 0) local self = { dict = dict, limit = limit, window = window, } return setmetatable(self, mt) end
syntax: delay, err = obj:incoming(key, commit)
触发新请求传入事件并计算当前请求对指定 key 所需的 delay(若是有的话),或者是否当即拒绝该请求。rest
该方法接受以下参数:code
key
: 是用户指定限制速率的 key。commit
:布尔值。若是设置为 true,则 obj 将会在支持该 obj 的共享内存中记录该事件;不然仅仅是 "dry run"。该 incoming 方法的放回值依赖以下状况:server
function _M.incoming(self, key, commit) local dict = self.dict local limit = self.limit local window = self.window local remaining, ok, err if commit then remaining, err = dict:incr(key, -1, limit) if not remaining then return nil, err end if remaining == limit - 1 then ok, err = dict:expire(key, window) if not ok then if err == "not found" then remaining, err = dict:incr(key, -1, limit) if not remaining then return nil, err end ok, err = dict:expire(key, window) if not ok then return nil, err end else return nil, err end end end else remaining = (dict:get(key) or limit) - 1 end if remaining < 0 then return nil, "rejected" end return 0, remaining end