nginx嵌入lua做接口保护流量限制

2022-09-13 16:01:44 浏览数 (1)

nginx嵌入lua限制每秒每分钟请求接口次数

在nginx层限制API每秒以及每分钟的请求次数,防止进程被打满。

保护接口

nginx.conf文件

代码语言:javascript复制
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文件

代码语言:javascript复制
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

0 人点赞