resty.limit.conn 限制并发请求的lua模块
限制接口总并发数
场景:按照 ip 限制其并发链接数nginx
1.共享内存加入到nginx的http标签:算法
[root@VM_82_178_centos vhost]# grep my_limit_conn_store /usr/local/openresty/nginx/conf/nginx.conf lua_shared_dict my_limit_conn_store 10m;
2.limit.conn.lua 模块lua脚本以下:centos
[root@VM_82_178_centos limit_lua]# cat /usr/local/openresty/nginx/conf/limit_lua/limit.conn.lua local limit_conn = require "resty.limit.conn" --限制200个并发请求下的请求和一个100个并发的额外的突发请求。也就是咱们延迟 --请求300个并发链接之内以及200个以上链接,并拒绝任何超过300的新请求链接。 --另外,咱们假设默认请求时间为0.5秒,也就是说经过下面的log_by_lua中的leaving()调用动态调整。 --以上是官网给的配置参数的的说明介绍。("my_limit_conn_store", 200, 100, 0.5) 这个是官网给的参数 --咱们能够调整参数为以下("my_limit_conn_store", 1, 0, 0.5) -- 限制一个 ip 客户端最大 1 个并发请求 -- burst 设置为 0,若是超过最大的并发请求数,则直接返回503, -- 若是此处要容许突增的并发数,能够修改 burst 的值(漏桶的桶容量) -- 最后一个参数实际上是你要预估这些并发(或者说单个请求)要处理多久,以便于对桶里面的请求应用漏桶算法 local lim, err = limit_conn.new("my_limit_conn_store", 200, 100, 0.5) if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.conn object: ", err) return ngx.exit(500) end --如下调用必须是每一个请求。 这里咱们使用远程(IP)地址做为限制key -- commit 为true 表明要更新shared dict中key的值, -- false 表明只是查看当前请求要处理的延时状况和前面还未被处理的请求数 local key = ngx.var.binary_remote_addr local delay, err = lim:incoming(key, true) if not delay then if err == "rejected" then return ngx.exit(503) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end ---- 若是请求链接计数等信息被加到shared dict中,则在ctx中记录下, -- 由于后面要告知链接断开,以处理其余链接 if lim:is_committed() then local ctx = ngx.ctx ctx.limit_conn = lim ctx.limit_conn_key = key ctx.limit_conn_delay = delay end local conn = err -- 其实这里的 delay 确定是上面说的并发处理时间的整数倍, -- 举个例子,每秒处理100并发,桶容量200个,当时同时来500个并发,则200个拒掉 -- 100个在被处理,而后200个进入桶中暂存,被暂存的这200个链接中,0-100个链接其实应该延后0.5秒处理, -- 101-200个则应该延后0.5*2=1秒处理(0.5是上面预估的并发处理时间) if delay >= 0.001 then --请求超过200链接比但低于300个链接,因此咱们故意将它延迟到这里以符合200链接限制。 ngx.sleep(delay) end
3.关于log_by_lua_block段的log_by_lua.lua 脚本以下:并发
[root@VM_82_178_centos limit_lua]# cat /usr/local/openresty/nginx/conf/limit_lua/log_by_lua.lua local ctx = ngx.ctx local lim = ctx.limit_conn if lim then --若是您在内容阶段使用上游模块 --那么你可能想要使用$ upstream_response_time 响应时间而不是($ request_time - ctx.limit_conn_delay)的时间 local latency = tonumber(ngx.var.request_time) - ctx.limit_conn_delay local key = ctx.limit_conn_key -- 这个链接处理完后应该告知一下,更新shared dict中的值,让后续链接能够接入进来处理 -- 此处能够动态更新你以前的预估时间,可是别忘了把limit_conn.new这个方法抽出去写, -- 要不每次请求进来又会重置 assert(key) local conn, err = lim:leaving(key, latency) if not conn then ngx.log(ngx.ERR,"failed to record the connection leaving ","request: ", err) return end end
测试说明:ide