Openresty之resty.limit.conn模塊介紹

resty.limit.conn 限制併發請求的lua模塊
限制接口總併發數
場景:按照 ip 限制其併發連接數

openresty開啓resty.limit.conn模塊具體配置過程如下:

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腳本如下:


[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

測試說明:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章