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
Last modification:February 7, 2022
如果觉得我的文章对你有用,请随意赞赏