虽然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(最实时的数据,进入这里就是没降级)")