1. 程式人生 > >Nginx + LUA下流量攔截算法

Nginx + LUA下流量攔截算法

str 支持 CA 購物車結算 Go 人的 bold word als

前言

每逢大促必壓測,每逢大促必限流,這估計是電商人的常態。每次大促期間,業務流量是平時的幾倍十幾倍,大促期間大部分業務都會集中在購物車結算,必須限流,才能保證系統不宕機。

限流算法

限流算法一般有三種:令牌桶,漏桶,計數器。本文介紹最粗暴的計數器算法,其他算法請自行google、百度,講的應該比我好。(能解決問題的算法都是好算法)

lua 限流

業務結構

技術分享圖片

在大促期間由於流量過高,現有服務器無法承受那麽大的流量,租用雲服務是很好的選擇。

業務架構圖可以看出 ,我們的服務器有自有服務器,首都在線雲,金山雲。自有服務器由於采購時間原因,每個批次的服務器性能不是很一致,首都在線雲、金山雲的服務器性能又有很大的差別,

lvs在權重設置上也有很大的不同,這對我們使用lua限流又造成了一定的困擾。當然這只是小問題,既然lvs只是權重,那麽我們的lua限流也支持權重即可。

nginx+lua

使用nginx+lua的原因很簡單,我們服務架構nginx+fastcgi+php,為了防止php進程被打滿,我們只需要在nginx加一層限制,就可以簡單粗暴的解決問題,而lua正好滿足這個條件。業務場景的不同,我們選擇的算法也不同,越是復雜的東西,越希望最簡單話的解決方案。引入越多的東西,就會造成更多的不確定性。

話不多說上代

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 ngx.header.content_type = "text/html; charset=utf-8"; local method=ngx.req.get_method() local curl=ngx.md5(ngx.var.request_uri); local request_uri_without_args = ngx.re.sub(ngx.var.request_uri, "\\?.*", ""); local match = string.match local ngxmatch=ngx.re.match --限流計數 function limit_url_check(key,s,m)
   local localkey=key;    local yyy_limit=ngx.shared.url_limit         --每分鐘限制 local key_m_limit= localkey..os.date("%Y-%m-%d %H:%M", ngx.time()) --每秒限制 local key_s_limit= localkey..os.date("%Y-%m-%d %H:%M:%S", ngx.time()) local req_key,_=yyy_limit:get(localkey); local req_key_s,_=yyy_limit:get(key_s_limit); local req_key_m,_=yyy_limit:get(key_m_limit); --每秒處理 if req_key_s then yyy_limit:incr(key_s_limit,1) if req_key_s>s then --return true                return false end    else yyy_limit:set(key_s_limit,1,60)    end         --每分鐘處理 if req_key_m then yyy_limit:incr(key_m_limit,1) if req_key_m>m then --return true return false end         else yyy_limit:set(key_m_limit,1,85)         end         return false end

代碼很簡單,但是很實用,看一下調用

1 2 3 4 5 6 7 if ngx.re.match(request_uri_without_args,"/cart/inf(.*)") then       if limit_url_check("appcartinfo",24,3200) then           ngx.say(‘{"code": 524,"msg": "啊啊啊,每逢大促,排隊結賬。當前訪問的用戶過多,請稍後再試!","alert": "啊啊啊,每逢大促,排隊結賬。當前訪問的用戶過多,請稍後再試!"}‘)           ngx.exit(200);   return       end end

調用的代碼秒,分鐘的限制數可以放到cjson中配置。

Nginx + LUA下流量攔截算法