openresty+lua+redis 实现访问限流

直接上代码吧

local function close_redis(red)
    if not red then
        return
    end
    -- 释放连接(连接池实现),毫秒
    local pool_max_idle_time = 30000
    -- 连接池大小
    local pool_size = 100
    local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
    local log = ngx_log
    if not ok then
        log(ngx_ERR, "set redis keepalive error : ", err)
    end
end

-- 连接redis
local redis = require('resty.redis')
local red = redis.new()
red:set_timeout(1000)

local ip = "127.0.0.1"
local port = "6379"
local ok, err = red:connect(ip,port)
if not ok then
    return close_redis(red)
end
--red:auth('123456')
--red:select('0')
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
   clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
   clientIP = ngx.var.remote_addr
end
-local incrKey = "user:"..clientIP..":freq"                                                                                   
local blockKey = "user:"..clientIP..":block"                                                                                   
                                                                                                                               
local is_block,err = red:get(blockKey) --check if ip is blocked                                                                
if tonumber(is_block) == 1 then                                                                                                
    ngx.exit(403)                                                                                                              
    close_redis(red)                                                                                                           
end                                                                                                                            
--inc  = red:incr(incrKey)                                                                                                     
--if inc < 10 then                                                                                                             
--inc = red:expire(incrKey,1)                                                                                                  
--end                                                                                                                          
-- 每秒10次以上访问即视为非法,会阻止1分钟的访问                                                                               
--if inc > 10 then                                                                                                             
    --设置block 为 True 为1                                                                                                    
--    red:set(blockKey,1)                                                                                                      
--    red:expire(blockKey,20)                                                                                                  
--end                                                                                                                          
close_redis(red)                    

 

这是一个根据时间计数器实现的限流功能。大概就是在多少时间内访问次数超过多少次就会被封禁。计数的实现也是利用lua调用redis实现的,通过让key每次访问增加1来计算。如果能通过外部的大数据平台来计算,然后把计算结果存在redis,lua只调用redis看访问的源IP是否在redis中,这样可以更大限度的节省性能开支。

 

posted @ 2024-10-25 14:07  羊脂玉净瓶  阅读(19)  评论(0)    收藏  举报