sponsored links

看看阿里程式設計師是怎樣講限流的

看看阿里程式設計師是怎樣講限流的

服務降級

將系統的所有功能服務進行一個分級,當系統出現問題需要緊急限流時,可將不是那麼重要的功能進行降級處理,停止服務,這樣可以釋放出更多的資源供給核心功能的去用。

例如在電商平臺中,如果突發流量激增,可臨時將商品評論、積分等非核心功能進行降級,停止這些服務,釋放出機器和CPU等資源來保障使用者正常下單,而這些降級的功能服務可以等整個系統恢復正常後,再來啟動,進行補單/補償處理。除了功能降級以外,還可以採用不直接操作資料庫,而全部讀快取、寫快取的方式作為臨時降級方案。

延遲處理

這個模式需要在系統的前端設定一個流量緩衝池,將所有的請求全部緩衝進這個池子,不立即處理。然後後端真正的業務處理程式從這個池子中取出請求依次處理,常見的可以用佇列模式來實現。這就相當於用非同步的方式去減少了後端的處理壓力,但是當流量較大時,後端的處理能力有限,緩衝池裡的請求可能處理不及時,會有一定程度延遲。後面具體的漏桶演算法以及令牌桶演算法就是這個思路。

特權處理

這個模式需要將使用者進行分類,透過預設的分類,讓系統優先處理需要高保障的使用者群體,其它使用者群的請求就會延遲處理或者直接不處理。

快取、降級、限流區別

快取,是用來增加系統吞吐量,提升訪問速度提供高併發。

降級,是在系統某些服務元件不可用的時候、流量暴增、資源耗盡等情況下,暫時遮蔽掉出問題的服務,繼續提供降級服務,給使用者儘可能的友好提示,返回兜底資料,不會影響整體業務流程,待問題解決再重新上線服務

限流,是指在使用快取和降級無效的場景。比如當達到閾值後限制介面呼叫頻率,訪問次數,庫存個數等,在出現服務不可用之前,提前把服務降級。只服務好一部分使用者。

限流的演算法

限流演算法很多,常見的有三類,分別是計數器演算法、漏桶演算法、令牌桶演算法,下面逐一講解。

計數器演算法

簡單粗暴,比如指定執行緒池大小,指定資料庫連線池大小、nginx連線數等,這都屬於計數器演算法。

計數器演算法是限流演算法裡最簡單也是最容易實現的一種演算法。舉個例子,比如我們規定對於A介面,我們1分鐘的訪問次數不能超過100個。那麼我們可以這麼做:在一開 始的時候,我們可以設定一個計數器counter,每當一個請求過來的時候,counter就加1,如果counter的值大於100並且該請求與第一個請求的間隔時間還在1分鐘之內,那麼說明請求數過多,拒絕訪問;如果該請求與第一個請求的間隔時間大於1分鐘,且counter的值還在限流範圍內,那麼就重置 counter,就是這麼簡單粗暴。

看看阿里程式設計師是怎樣講限流的

漏桶演算法

漏桶演算法思路很簡單,水(請求)先進入到漏桶裡,漏桶以一定的速度出水,當水流入速度過大會超過桶可接納的容量時直接溢位,可以看出漏桶演算法能強行限制資料的傳輸速率。

看看阿里程式設計師是怎樣講限流的

這樣做的好處是:

削峰:有大量流量進入時,會發生溢位,從而限流保護服務可用

緩衝:不至於直接請求到伺服器,緩衝壓力 消費速度固定 因為計算效能固定

令牌桶演算法

令牌桶與漏桶相似,不同的是令牌桶桶中放了一些令牌,服務請求到達後,要獲取令牌之後才會得到服務,舉個例子,我們平時去食堂吃飯,都是在食堂內視窗前排隊的,這就好比是漏桶演算法,大量的人員聚集在食堂內視窗外,以一定的速度享受服務,如果湧進來的人太多,食堂裝不下了,可能就有一部分人站到食堂外了,這就沒有享受到食堂的服務,稱之為溢位,溢位可以繼續請求,也就是繼續排隊,那麼這樣有什麼問題呢?

如果這時候有特殊情況,比如有些趕時間的志願者啦、或者高三要高考啦,這種情況就是突發情況,如果也用漏桶演算法那也得慢慢排隊,這也就沒有解決我們的需求,對於很多應用場景來說,除了要求能夠限制資料的平均傳輸速率外,還要求允許某種程度的突發傳輸。這時候漏桶演算法可能就不合適了,令牌桶演算法更為適合。如圖所示,令牌桶演算法的原理是系統會以一個恆定的速度往桶裡放入令牌,而如果請求需要被處理,則需要先從桶裡獲取一個令牌,當桶裡沒有令牌可取時,則拒絕服務。

看看阿里程式設計師是怎樣講限流的

令牌桶好處就是,如果某一瞬間訪問量劇增或者有突發情況,可以透過改變桶中令牌數量來改變連線數,就好比那個食堂排隊吃飯的問題,如果現在不是直接去視窗排隊,而是先來樓外拿飯票然後再去排隊,那麼有高三的學生時可以將增加飯票數量或者優先將令牌給高三的學生,這樣比漏桶演算法更加靈活。

併發限流

簡單來說就是設定系統閾值總的QPS個數,這些也挺常見的,就拿Tomcat來說,很多引數就是出於這個考慮,例如

配置的acceptCount 設定響應連線數, maxConnections設定瞬時最大連線數, maxThreads 設定最大執行緒數,在各個框架或者元件中,併發限流體現在下面幾個方面:

  • 限制總併發數(如資料庫連線池、執行緒池)
  • 限制瞬時併發數(nginx的limit_conn模組,用來限制瞬時併發連線數)
  • 限制時間視窗內的平均速率(如Guava的RateLimiter、nginx的limit_req模組,限制每秒的平均速率)
  • 其他的還有限制遠端介面呼叫速率、限制MQ的消費速率。
  • 另外還可以根據網路連線數、網路流量、CPU或記憶體負載等來限流。

有了併發限流,就意味著在處理高併發的時候多了一種保護機制,不用擔心瞬間流量導致系統掛掉或雪崩,最終做到有損服務而不是不服務;但是限流需要評估好,不能亂用,否則一些正常流量出現一些奇怪的問題而導致使用者體驗很差造成使用者流失。

介面限流

介面限流分為兩個部分,一是限制一段時間內介面呼叫次數,參照前面限流演算法的計數器演算法, 二是設定滑動時間視窗演算法。

介面總數

控制一段時間內介面被呼叫的總數量,可以參考前面的計數器演算法,不再贅述。

介面時間視窗

固定時間視窗演算法(也就是前面提到的計數器演算法)的問題是統計區間太大,限流不夠精確,而且在第二個統計區間 時沒有考慮與前一個統計區間的關係與影響(第一個區間後半段 + 第二個區間前半段也是一分鐘)。為了解決上面我們提到的臨界問題,我們試圖把每個統計區間分為更小的統計區間,更精確的統計計數。

看看阿里程式設計師是怎樣講限流的

在上面的例子中,假設QPS可以接受100次查詢/秒, 前一分鐘前40秒訪問很低,後20秒突增,並且這個持續了一段時間,直到第二分鐘的第40秒才開始降下來,根據前面的計數方法,前一秒的QPS為94,後一秒的QPS為92,那麼沒有超過設定引數,但是!但是在中間區域,QPS達到了142,這明顯超過了我們的允許的服務請求數目,所以固定視窗計數器不太可靠,需要滑動視窗計數器。

計數器演算法其實就是固定視窗演算法, 只是它沒有對時間視窗做進一步地劃分,所以只有1格;由此可見,當滑動視窗的格子劃分的越多,也就是將秒精確到毫秒或者納秒, 那麼滑動視窗的滾動就越平滑,限流的統計就會越精確。

需要注意的是,消耗的空間就越多。

限流實現

這一部分是限流的具體實現,簡單說說,畢竟長篇程式碼沒人願意看。

guava實現

引入包

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.1-jre</version>
</dependency>

複製程式碼

核心程式碼

  LoadingCache<Long, AtomicLong> counter = CacheBuilder.newBuilder().
    expireAfterWrite(2, TimeUnit.SECONDS)
    .build(new CacheLoader<Long, AtomicLong>() {

     @Override
     public AtomicLong load(Long secend) throws Exception {
      // TODO Auto-generated method stub
      return new AtomicLong(0);
     }
    });
  counter.get(1l).incrementAndGet();

複製程式碼

令牌桶實現

穩定模式(SmoothBursty:令牌生成速度恆定)

 public static void main(String[] args) {
  // RateLimiter.create(2)每秒產生的令牌數
  RateLimiter limiter = RateLimiter.create(2);
        // limiter.acquire() 阻塞的方式獲取令牌
  System.out.println(limiter.acquire());;
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;

  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;
 }

複製程式碼

`RateLimiter.create(2) 容量和突發量,令牌桶演算法允許將一段時間內沒有消費的令牌暫存到令牌桶中,用來突發消費。

漸進模式(SmoothWarmingUp:令牌生成速度緩慢提升直到維持在一個穩定值)

 // 平滑限流,從冷啟動速率(滿的)到平均消費速率的時間間隔
  RateLimiter limiter = RateLimiter.create(2,1000l,TimeUnit.MILLISECONDS);
  System.out.println(limiter.acquire());;
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;

  System.out.println(limiter.acquire());;
  System.out.println(limiter.acquire());;

複製程式碼

超時

boolean tryAcquire = limiter.tryAcquire(Duration.ofMillis(11));

複製程式碼

在timeout時間內是否能夠獲得令牌,非同步執行

分散式系統限流

Nginx + Lua實現

可以使用resty.lock保持原子特性,請求之間不會產生鎖的重入

https://github.com/openresty/lua-resty-lock

使用lua_shared_dict儲存資料

local locks = require "resty.lock"

local function acquire()
    local lock =locks:new("locks")
    local elapsed, err =lock:lock("limit_key") --互斥鎖 保證原子特性
    local limit_counter =ngx.shared.limit_counter --計數器

    local key = "ip:" ..os.time()
    local limit = 5 --限流大小
    local current =limit_counter:get(key)

    if current ~= nil and current + 1> limit then --如果超出限流大小
       lock:unlock()
       return 0
    end
    if current == nil then
       limit_counter:set(key, 1, 1) --第一次需要設定過期時間,設定key的值為1,
--過期時間為1秒
    else
        limit_counter:incr(key, 1) --第二次開始加1即可
    end
    lock:unlock()
    return 1
end
ngx.print(acquire())
分類: 遊戲
時間: 2021-12-21

相關文章

FPX預測總勝率最高,一血率卻低的可憐,他們為何依舊能這麼強?

FPX預測總勝率最高,一血率卻低的可憐,他們為何依舊能這麼強?
英雄聯盟S11全球總決賽越來越近了,今年的參賽隊伍實力也都是相當強大,對決讓人充滿期待,老隊伍依舊霸佔著一席之地,單屆冠軍隊伍就有五支,多次參加世界賽的老牌戰隊更多,最近,外國媒體公佈了世界賽的參賽隊 ...

S11參賽隊伍,世界賽勝率第一竟然是LPL中國賽區的FPX

S11參賽隊伍,世界賽勝率第一竟然是LPL中國賽區的FPX
9月22號,也就是明天將舉行S11英雄聯盟全球總決賽抽籤儀式.屆時我們可以看到每個戰隊的分組,並預測自己喜歡看好的哪些戰隊將在bo5(五局三勝制)中碰面.這一屆S賽,有些戰隊在此前的世界賽中的成績非常 ...

LOL:S11小組抽籤儀式更新,重劃四大賽區,RNG沒能和T1分在一組

LOL:S11小組抽籤儀式更新,重劃四大賽區,RNG沒能和T1分在一組
相信關注英雄聯盟賽事的小夥伴們都知道,LOL最受矚目的莫過於一年一度全球總決賽.而隨著比賽時間的臨近,S11小組賽抽籤儀式的時間終於敲定,來自全球各賽區的22支戰隊將要參加入圍賽和小組賽的抽籤,來確定 ...

S11戰隊巡禮-RNG:全華班的最後驕傲,MSI冠軍不容小覷

S11戰隊巡禮-RNG:全華班的最後驕傲,MSI冠軍不容小覷
RNG全名ROYAL NEVER GIVE UP,俱樂部成立於2012年5月,而其旗下的英雄聯盟戰隊是一支LPL的傳統豪門.本賽季的RNG並沒有進行太大的人員變動,由於在休賽期RNG戰隊並沒有招募到合 ...

2021世界賽戰隊巡禮PCE:建隊第一年就晉級世界賽,打野值得關注

2021世界賽戰隊巡禮PCE:建隊第一年就晉級世界賽,打野值得關注
隨著2021年世界賽的到來,英雄聯盟大洋洲的PEACE是來自全球的22支隊伍之一,他們正在為今年最大和最重要的比賽做著準備.世界賽每年都有每個賽區的精英隊伍參加,他們都在為一個終極目標而戰:站在山頂上 ...

PCS5洲際賽:韓國戰隊首周奪冠,CTG亞軍輸在圈運,17戰隊又拉了

PCS5洲際賽:韓國戰隊首周奪冠,CTG亞軍輸在圈運,17戰隊又拉了
北京時間9月19日,由鬥魚直播全程直播的PCS5洲際賽迎來第一週第二天的較量,毫無疑問吸引了眾多網友關注.回顧首日揭幕戰的戰況,PCL賽區除了PeRo戰隊狀態線上.CTG吃到一雞之外,其他隊伍手感不佳 ...

紫金王朝迴歸!NV-騰訊影片戰隊斬獲PEL 2021 S3第四周百萬周冠軍

紫金王朝迴歸!NV-騰訊影片戰隊斬獲PEL 2021 S3第四周百萬周冠軍
9月19日,2021 PEL S3第四周周決賽落下帷幕,NV-騰訊影片戰隊憑藉出色的發揮,以113總分登上積分榜第一位,獲得百萬周冠軍,WBG戰隊獲得第二名,RNG戰隊位居第三. 穩定與爆發兼具,NV ...

Faker:世界賽想跟EDG或FPX交手,沒有什麼特別想面對的選手

Faker:世界賽想跟EDG或FPX交手,沒有什麼特別想面對的選手
Faker:世界賽想跟EDG或FPX交手,沒有什麼特別想面對的選手,我想把注意力放在如何提高自己上 隨著T1在區域預選賽中擊敗HEL,他們也是確定拿到了LCK的三號種子,將直通S11世界賽的小組賽階段 ...

盤點S11全球總決賽10大新秀!誰能夠一戰成名?

盤點S11全球總決賽10大新秀!誰能夠一戰成名?
★遊戲馬蹄鐵原創 LOL今年的全球總決賽上有不少新人,其中一部分已經成為戰隊的首發主力,而另外一部分則有可能成為S11上的秘密武器或者只是順帶旅遊的陪跑成員.LOL職業聯賽的年齡層已經逐漸進入到了00 ...

昔日歐洲霸主G2隕落!院長Caps發話:大家打得不夠團結

昔日歐洲霸主G2隕落!院長Caps發話:大家打得不夠團結
英雄聯盟2021全球總決賽距離開賽還有不到半個月時間了,談到今年的世界賽,很多玩家都表示,這可能會是近年來最精彩的一屆,因為有著不少的遠古豪強迴歸,有老將再度來到世界賽也有新人開始自己的新徵程,總得來 ...

絕地求生:V7奪冠,CTG驚豔眾人,NH排名第七,17開始劇本了?

絕地求生:V7奪冠,CTG驚豔眾人,NH排名第七,17開始劇本了?
Hello,大家好,我是千言. 隨著本週最後一場比賽落幕,我們亞太賽區PCS5洲際賽第一週的比賽也是畫上了句號.而最終的結果也是意料之外,但卻是情理之中!畢竟說實話,能來到洲際賽舞臺的隊伍都肯定不是弱 ...

毛主席唯一戴過的手錶:是郭沫若贈送的歐米茄,戴了31年直到逝世

毛主席唯一戴過的手錶:是郭沫若贈送的歐米茄,戴了31年直到逝世
1961年,毛主席在廬山參加會議,文工團的女演員邢韻聲注意到戴在毛主席手腕上的一塊舊錶,那塊表的錶帶已經磨爛了,錶盤也已經發黃且佈滿劃痕,看起來太過陳舊.邢韻聲非常疑惑,偉大領袖毛主席怎麼會戴著這樣一 ...

魅藍手機迴歸後首曝:驍龍870+超窄直屏!白色面板有戲了?

魅藍手機迴歸後首曝:驍龍870+超窄直屏!白色面板有戲了?
正當人們都已經習慣魅族作為國產手機的小眾品牌時,魅族官方前兩天卻突然宣佈闊別已久的魅藍品牌重新迴歸,同時還將一口氣帶來三款機型.雖然不知道這三款新機是否都屬於魅藍品牌,但作為曾經不少人的回憶,魅藍手機 ...

不拿金牌的“球王”不是好會計!40歲的他第一次參加全運會就拿了冠軍

不拿金牌的“球王”不是好會計!40歲的他第一次參加全運會就拿了冠軍
如果說有選手在乒乓球專案上為黑龍江隊拿到了十四運金牌,您想到的人選肯定會是新科奧運冠軍王曼昱,或者是名將車曉曦.然而,拿到金牌的卻是很多人都沒聽過的名字--袁磊. 18 日上午,在寶雞市體育館進行的十 ...

C盤不夠用?圖片功能太簡單?Win 11這些改進可以瞭解一下

C盤不夠用?圖片功能太簡單?Win 11這些改進可以瞭解一下
C盤空間不夠用?這似乎是Windows XP時代就留下的病根,而現在,事情似乎有了轉機. 01 Win11改進了硬碟空間佔用和效能表現 微軟已宣佈將於 10 月 5 日正式推出下一代 Windows ...

今年去世界賽的選手中哪個國家的人最多呢?

今年去世界賽的選手中哪個國家的人最多呢?
S11馬上要開始了,LOL資料庫fandom做了一個選手國籍的統計. 排在第一的國家是韓國,韓國此次將有41位選手參與,其中小組賽13人,入圍賽28人. 第二多的國家為中國,其中大陸21人臺灣省9人香 ...

賈府大廈傾塌之後,這三個女子過上了幸福的生活

賈府大廈傾塌之後,這三個女子過上了幸福的生活
作為四大名著之首的<紅樓夢>,它是一部封建社會的悲歌,全文以賈史王薛四大家族的衰亡為線索,描述了一段大觀園由歡樂走向分離的白茫茫一片真大地真乾淨的淒涼歷程. 只是,若我們用心品讀,卻能發現 ...

革命者豈能貪財——陳贊賢烈士的故事
在風景秀麗的贛州八境公園內,有一座烈士紀念亭.這座紀念亭,建成於1955年5月,是江西省贛州城區內紀念陳贊賢烈士唯一的一座建築物. 坐落在贛州八境公園內的陳贊賢烈士紀念亭 陳贊賢(1896-1927) ...

CBA官方:北控球員王少傑因擅自離開賽區官方酒店 罰款1萬元、停賽2場

CBA官方:北控球員王少傑因擅自離開賽區官方酒店 罰款1萬元、停賽2場
齊魯網·閃電新聞10月11日訊 新賽季CBA聯賽開賽在即,不過比賽雖暫未開啟,但是卻有球員違反防疫規定被處罰. 今天上午,山東電視體育頻道記者從中國男子籃球職業聯賽官方網站獲悉,10月9日北控球隊抵達 ...

狼人殺官方WPL決賽前的狂歡,眾人氣明星、主播齊聚9月22日表演賽

狼人殺官方WPL決賽前的狂歡,眾人氣明星、主播齊聚9月22日表演賽
前言:由網易<狼人殺官方>主辦的狼人殺英雄聯賽WPL 2021即將來到決賽階段,12支強隊即將開始爭奪至高無上的冠軍寶座.不過在決賽開賽前,9月20~22日,還有多場雲集各路大神主播,CV ...