前言

虽然nginx中自带了限流的模块,只能直接限定超出的数量,但对于允许范围内的流量如何进行限流是个问题。nginx的限流方式!



 limit_conn perserver 100;


 limit_conn perip 15;


 limit_rate 512k;


但是比如这100的允许的值,0-30个请求去mysql读数据,31-70去redis读数据,71-100去文件直接读数据,nginx不好做这个事情,所以引入lua的lua-resty-limit-traffic来设计。



local limit_req = require "resty.limit.req"


-- 这里设置rate=50个请求/每秒,漏桶桶容量设置为1000个请求


-- 因为模块中控制粒度为毫秒级别,所以可以做到毫秒级别的平滑处理


-- my_limit_req_store是共享内存,请在http中设置一下  lua_shared_dict my_limit_req_store 100m;


local lim, err = limit_req.new("my_limit_req_store", 50, 1000)


if not lim then


    ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)


    return ngx.exit(501)


end


 


local key = ngx.var.binary_remote_addr


local delay, err = lim:incoming(key, true)


 


 


ngx.say("计算出来的延迟时间是:")


ngx.say(delay)


 


--if ( delay <0 or delay==nil ) then


    --return ngx.exit(502)


--end


 


 


-- 1000以外的就溢出


if not delay then


    if err == "rejected" then


        return ngx.say("1000以外的就溢出")


        -- return ngx.exit(502)


    end


    ngx.log(ngx.ERR, "failed to limit req: ", err)


    return ngx.exit(502)


end


 


-- 50-100的等待从微服务+mysql获取实时数据;(100-50)/50 =1


if ( delay >0 and delay <=1 ) then


    ngx.say("第50-第100个 等待0-1秒后 从mysql获取数据")


    ngx.sleep(delay)


 


-- 100-400的直接从redis获取实时性略差的数据;(400-50)/50 =7


elseif ( delay >1 and delay <=7 ) then


    local resp, err = redis_instance:get("redis_goods_list_advert")


    ngx.say("第100-第400个 降级为从redis获取数据")


    ngx.say(resp)


    return


 


-- 400-1000的从静态文件获取实时性非常低的数据(1000-50)/50 =19


elseif ( delay >7) then


 


    ngx.say("第400-第1000个 降级为从静态文件(死页面)获取数据")


    ngx.header.content_type="application/x-javascript;charset=utf-8"


    local file = "/etc/nginx/html/goods_list_advert.json"


    local f = io.open(file, "rb")


    local content = f:read("*all")


    f:close()


    ngx.print(content)


    return


end


 


 


ngx.say("进入查询微服务+mysql(最实时的数据,进入这里就是没降级)")