一、openresty實現限流說明:
靜態攔截和動態攔截介紹:
靜態攔截就是限流某一個接口在一定時間單位的請求數。一般就是單位1s內的客戶端的請求數。
例如用戶可以在系統上給他們的接口配置一個每秒最大調用量,如果超過這個限制,則拒絕服務此接口。
而動態攔截其實也是基於靜態攔截進行改進,我們可以依據當前系統的響應時間來動態調整限流的閾值,如果響應較快則可以把閾值調的大一些,
放過更多請求,反之則自動降低限流閾值,只使少量請求通過。
其實這就是一個很簡單的限流方式。但是因爲這些場景在我們開發的時候經常遇到,然而OpenResty 大概實現一些常見的限流方式。
(此處使用OpenResty1.13.6.1版本自帶lua-resty-limit-traffic模塊 ,實現起來更爲方便)。只要是openresty版本號大於1.13.6.1的,都是默認自帶lua-resty-limit-traffic模塊的
如果,OpenResty版本低於1.13.6.1 ,則需要下載限流模塊,下面是下載地址:
git clone https://github.com/openresty/lua-resty-limit-traffic.git
二、平滑限制請求數
2.1具體配置過程如下:
平滑限制請求數(使用漏桶的方法)
場景:
限制 ip 每分鐘只能調用 120 次 /1.html 接口文件(平滑處理請求,即每秒放過2個請求)
共享內存加入到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的 虛擬主機配置文件如下:
[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腳本內容如下:
[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
2.2詳細說明以下lua腳本限流的實現過程:
[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
2.2 limit.req.lua 漏桶方法具體介紹如下:
此模塊提供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模塊更靈活,因爲它可以在幾乎任意的上下文中使用。
具體測試可以把上面的請求次數調整的小點,來模擬測試