原文: 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