靜態攔截和動態攔截介紹:
靜態攔截就是限流某一個接口在必定時間單位的請求數。通常就是單位1s內的客戶端的請求數。
例如用戶能夠在系統上給他們的接口配置一個每秒最大調用量,若是超過這個限制,則拒絕服務此接口。
而動態攔截其實也是基於靜態攔截進行改進,咱們能夠依據當前系統的響應時間來動態調整限流的閾值,若是響應較快則能夠把閾值調的大一些,
放過更多請求,反之則自動下降限流閾值,只使少許請求經過。php
其實這就是一個很簡單的限流方式。可是由於這些場景在咱們開發的時候常常遇到,然而OpenResty 大概實現一些常見的限流方式。
(此處使用OpenResty1.13.6.1版本自帶lua-resty-limit-traffic模塊 ,實現起來更爲方便)。只要是openresty版本號大於1.13.6.1的,都是默認自帶lua-resty-limit-traffic模塊的html
若是,OpenResty版本低於1.13.6.1 ,則須要下載限流模塊,下面是下載地址:
git clone https://github.com/openresty/lua-resty-limit-traffic.gitnginx
平滑限制請求數(使用漏桶的方法)
場景:
限制 ip 每分鐘只能調用 120 次 /1.html 接口文件(平滑處理請求,即每秒放過2個請求)git
共享內存加入到nginx的http標籤:程序員
lua_shared_dict my_limit_req_store 10m; [root@VM_82_178_centos ~]# grep lua_shared_dict /usr/local/openresty/nginx/conf/nginx.conf #lua_shared_dict log_list 1024m; lua_shared_dict my_limit_req_store 10m;
nginx的 虛擬主機配置文件以下:github
[root@VM_82_178_centos limit_lua]# cat /usr/local/openresty/nginx/conf/vhost/limit_req.conf server { listen 80; server_name 01limit.req.com; index index.html index.htm index.php; root /data/www/test; location / { access_by_lua_file /usr/local/openresty/nginx/conf/limit_lua/limit.req.lua; default_type 'text/html'; #content_by_lua 'ngx.say("hello world")'; access_log /data/wwwlog/01ip_access.log ; } }
平滑限制接口請求數的lua腳本內容以下:centos
[root@VM_82_178_centos limit]# cat /usr/local/openresty/nginx/conf/limit_lua/limit.req.lua local limit_req = require "resty.limit.req" local lim, err = limit_req.new("my_limit_req_store", 2, 0) -- 這裏設置rate=2/s,漏桶桶容量設置爲0,(也就是來多少水就留多少水) -- 由於resty.limit.req代碼中控制粒度爲毫秒級別,因此能夠作到毫秒級別的平滑處理 if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end 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(403) end --此處若是請求超過每秒2次的話,就會報錯403 ,禁止訪問 ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end if delay >= 0.001 then local excess = err ngx.sleep(delay) end
[root@VM_82_178_centos limit_lua]# cat /usr/local/openresty/nginx/conf/limit_lua/limit.req.lua local limit_req = require "resty.limit.req" --限制請求在每秒200次如下和併發請求每秒100次; --也就是咱們延遲每秒200次以上和每秒300次之內之間的請求; --而且每秒請求超過300次的都reject 拒絕掉 local lim, err = limit_req.new("my_limit_req_store", 200, 100) if not lim then ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500) end --下面的調用必須是每一個請求,在這裏咱們使用遠程ip(至關於客戶端的ip)做爲限制key值 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(403) end ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500) end if delay >= 0.001 then --第二個返回值包含超過每秒指定請求的數的值,例如:數值是31的話意思就是當前的請求的速率是231r/s(每秒231次請求), local excess = err --請求超過200r/s但低於300r/s,因此咱們故意將它延遲一點以符合200r/s的速率。 ngx.sleep(delay) end
此模塊提供API來幫助OpenResty / ngx_lua用戶程序員使用「漏桶」方法限制請求頻率,
若是要一次使用此類的多個不一樣實例或使用此類一個實例與其餘類的實例。例如:同時和resty.limit.conn這個模塊一塊使用的話,必須使用
resty.limit.traffic這個模塊把他們結合起來。
這個Lua模塊的實現相似於NGINX的標準模塊
[ngx_limit_req](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
可是這個Lua模塊更靈活,由於它能夠在幾乎任意的上下文中使用。併發
具體測試能夠把上面的請求次數調整的小點,來模擬測試ide