request-statistics.lua

--[[
实现请求统计,并且将单位时间内异常次数达到阀值的请求加入到黑名单中
--]]

--获取共享内存
local limit_req_store = ngx.shared.limit_req_store

--过载保护策略总开关,若开关关闭,则全部策略失效
local overload_protection_switch = limit_req_store:get("overload_protection_switch")
if (overload_protection_switch ~= nil and overload_protection_switch == "N") then
    ngx.log(ngx.INFO, "nginx limit strategy has been shutdown.")
    return
end

--获取返回状态码
local status = ngx.status

--获取请求uri
local uri = ngx.var.uri

ngx.log(ngx.DEBUG, "current request uri:", uri, ", http status code:", status)


local count        --记录当前请求的异常次数
local uri_last_decay_time_key="cur_time:"..uri     --记录当前请求上一次衰减时间节点的 key
local black_list_key = "black_list:"..uri        --记录异常次数达到上限时被加入黑名单的 URI 的 key
local os_cur_time = os.time()        --获取当前系统时间,单位是秒
local cur_uri = "cur:"..uri      --记录请求异常次数的 key,不能直接用 uri 做 key,会和resty-limit-multiple-strategy.lua文件中的key 冲突

--衰减时间内最大异常次数
local max_fail_time= limit_req_store:get("period_max_fail_time")
if (max_fail_time == nil or max_fail_time == 0) then
    max_fail_time = 50
end

ngx.log(ngx.DEBUG,"nginx config period_max_fail_time:",max_fail_time)

--衰减时间,所有与过期时间相关的设置单位都是秒
local decay_time= limit_req_store:get("period_time")
if (decay_time == nil or decay_time == 0) then
    decay_time = 20
end

--异常请求加入blacklist的有效时间,单位是秒
local black_list_time = limit_req_store:get("black_list_survival_time")
if (black_list_time == nil or black_list_time == 0) then
    black_list_time = 300
end

--err_code 默认为执行限流策略时的返回码,不需要后续逻辑处理
if status == err_code then
    return
end

--只统计400以上的返回异常
if status >= 400 then
    count= limit_req_store:get(cur_uri)
    if count == nil then
        limit_req_store:set(cur_uri,1)
        limit_req_store:set(uri_last_decay_time_key,os_cur_time)
        count = 1
    else
        --获取当前异常次数的值
        count = limit_req_store:incr(cur_uri,1)
    end
    --print("count-----:",count)
    if count >= tonumber(max_fail_time) then
        ngx.log(ngx.ERR, "nginx current request uri:", uri," fail time is up to the max_fail_time,and will be added to black_list.")
        limit_req_store:set(black_list_key,1,black_list_time)
        limit_req_store:delete(cur_uri)
        limit_req_store:delete(uri_last_decay_time_key)
        return
    end
    local time = limit_req_store:get(uri_last_decay_time_key)
    time = os_cur_time-time
    if time >= tonumber(decay_time) then
        --math.ceil()函数用户取整
        count = math.ceil(count/2)
        ngx.log(ngx.DEBUG, "nginx current request uri:", uri," fail time was be decayed,current count:", count)
        limit_req_store:set(cur_uri,count)
        limit_req_store:set(uri_last_decay_time_key,os_cur_time)
    end
end

猜你喜欢

转载自www.cnblogs.com/koushr/p/5873441.html
LUA