nginx嵌入lua限制每秒每分钟请求接口次数
- 在nginx层限制API每秒以及每分钟的请求次数,防止进程被打满。
保护接口
nginx.conf文件
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { # 设置纯 Lua 扩展库的搜寻路径(';;' 是默认路径) lua_package_path "/data/www/code/nginx+lua/config/lua_p/?.lua;;"; # 设置 C 编写的 Lua 扩展模块的搜寻路径(也可以用 ';;') lua_package_cpath "/data/www/code/nginx+lua/config/lua_p_c/?.so;;"; # 缓存大小5m lua_shared_dict url_limit 5m; server { listen 8080; location /limiter { lua_code_cache off; content_by_lua_file ./config/lua/limiter.lua; } } }
limiter.lua文件
ngx.header.content_type = "text/html; charset=utf-8"; local method = ngx.req.get_method(); local curl = ngx.md5(ngx.var.request_uri); local request_uri_without_args = ngx.re.sub(ngx.var.request_uri, "\\?.*", ""); local match = string.match; local ngxmatch = ngx.re.match; --限流计数 local function limit_url_check(key, s, m) local localkey = key; local yyy_limit = ngx.shared.url_limit; --每分钟限制 local key_m_limit = localkey .. os.date("%Y-%m-%d %H:%M", ngx.time()); --每秒限制 local key_s_limit = localkey .. os.date("%Y-%m-%d %H:%M:%S", ngx.time()); local req_key, _ = yyy_limit:get(localkey); local req_key_s, _ = yyy_limit:get(key_s_limit); local req_key_m, _ = yyy_limit:get(key_m_limit); --每秒处理 if req_key_s then yyy_limit:incr(key_s_limit, 1); if req_key_s > s then return false; end else yyy_limit:set(key_s_limit, 1, 60); end --每分钟处理 if req_key_m then yyy_limit:incr(key_m_limit, 1); if req_key_m > m then return false; end else yyy_limit:set(key_m_limit, 1, 85); end return true; end local url, err = ngx.re.match(request_uri_without_args, "/limiter"); if url then if not limit_url_check("limiter", 5, 15) then ngx.say('{"code": 1000,"msg":当前访问的用户过多,请稍后再试!"}'); ngx.exit(200); return; end end