lua 限流


前言

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

限流算法

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

lua 限流

業務結構

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

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

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

nginx+lua

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

話不多說上代

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

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

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中配置。

以上,歡迎大神給出意見建議。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM