聊聊限流的一些事兒

一、背景

最近幾年,隨著微服務的流行,服務與服務之間依賴越來越強,調用也越來越復雜,服務間的穩定性變突顯出來。特別是在遇到突發請求時,常常需要通過緩存、限流、熔斷降級、負載均衡等多種方式保證服務的穩定性。其中限流是不可或缺的一環。一般每一個對外提供的接口都需要做流量控制,這與保險絲的原理一樣。當接口的流量請求超過核定值時就得對請求進行引流或者直接拒絕等操作。特別是在系統應對大流量,高并發的訪問時,限流算法可以很好地控制流量,從而避免系統負載過高而崩潰。

二、限流算法

下面介紹的限流方式主要是窗口算法和桶算法,各有優勢。

  • 窗口算法實現簡單,邏輯清晰,可以很直觀的得到當前的 QPS 情況,但是會有時間窗口的臨界突變問題,而且不像桶一樣有隊列可以緩沖;另外,在細粒度上難以對流量曲線進行調整,即不能實現削峰填谷的效果,這可能對某些需要平滑流量的場景造成問題。限流簡單暴力,對于C端產品來說,這可能不是一種友好的選擇。
  • 桶算法雖然稍微復雜,不好統計 QPS 情況,但是桶算法也有優勢所在。
    • 漏桶模式消費速率恒定,可以很好的保護自身系統,可以對流量進行整形,但是面對突發流量不能快速響應。應用場景:自身服務調用第三方服務時,第三方服務需要我們來限制速度。
    • 令牌桶模式可以面對突發流量,但是啟動時會有緩慢加速的過程,不過常見的開源工具中已經對此優化。應用場景:別人調用自身服務時可以使用(畢竟對自身服務qps有一定的了解)。

限流算法

原理

優點

缺點

使用場景

流量整形

處理延時

滑動窗口

窗口在時間軸上滑動,記錄請求次數

實時控制,流量較均勻

難以實現流量曲線整形,無法削峰填谷

單機或單點網關限流

漏桶

流入請求如水流入桶,滿則丟棄

能夠控制突發流量(主要看容量)

流出速率恒定,對突發流量反應不夠快速

瞬時高并發流量場景或調第三方服務

令牌桶

以一定速率產生令牌,請求需拿令牌

可動態調整處理速度,允許突發流量在一定程序上得到滿足

實現復雜,以及令牌的數量控制

別人調用自身服務控制量級

2.1 漏桶算法

漏桶算法主要目的是控制請求速率,平滑網絡上的突發流量。如上圖示例,固定速率流出請求,流入請求速率任意,請求是否被處理看桶中的令牌是否足夠。它常用于限制網絡流量、控制數據傳輸率等場景,但是無法應用突發的高流量。

JSF不使用此類算法的原因:

1、由于漏桶出口速度固定,不能靈活應對后端能力的提升,如后端服務動態擴容后,漏桶沒有辦法。

2、無法有效利用資源,服務器處理能力并不是均衡絕對的,即任意時間都是固定的,如服務處理能力為1kqps,可能前6s為2k,后面時間為500,即一小段時間服務器資源是可以承受這段請求壓力的,但是漏桶算法在這種情況下會丟棄一部分請求。

2.2 令牌桶算法

令牌桶算法是另一種經典的限流算法,它的原理是將請求放入一個令牌桶中。然后按照一定速度不斷地放出令牌。只有在令牌桶中有令牌時,才能夠發出令牌。令牌桶算法可以控制單位時間內的請求速率,同時可以應對突發流量(累積令牌)如后端能力的提升,因為只有在足夠多的令牌,才可以放請求過去。

這里思考一個問題,令牌是如何添加的?如果按照指定時間間隔添加令牌,則需要開一個線程去定時添加,當有多個接口需要限流時,線程數就會隨之增加,這顯然不是一個好的辦法。在Guava的RateLimiter是這樣做的——每次令牌獲取時計算令牌是否足夠:它通過存儲的下一個令牌生成的時間,和當前獲取令牌的時間差,再結合閾值,去計算令牌是否足夠,同時再記錄下一個令牌的生成時間以便下一次調用。

下面是 Guava 中 RateLimiter 類的子類 SmoothRateLimiter 的resync()方法的代碼分析,可以看到其中的令牌計算邏輯。

void resync(long nowMicros) { // 當前微秒時間// 當前時間是否大于下一個令牌生成時間if (nowMicros > this.nextFreeTicketMicros) { // 可生成的令牌數 newPermits = (當前時間 - 下一個令牌生成時間)/ 令牌生成時間間隔。// 如果 QPS 為2,這里的 coolDownIntervalMicros 就是 500000.0 微秒(500ms)doublenewPermits= (double)(nowMicros - this.nextFreeTicketMicros) / this.coolDownIntervalMicros();// 更新令牌庫存 storedPermits。this.storedPermits = Math.min(this.maxPermits, this.storedPermits + newPermits);// 更新下一個令牌生成時間 nextFreeTicketMicrosthis.nextFreeTicketMicros = nowMicros;}
}

2.3 滑動窗口限流

滑動窗口限流將單位時間周期分為n個小周期,分別記錄每個小周期內接口的訪問次數,并且根據時間滑動刪除過期的小周期,每個小周期都有自己獨立的計數器。

當滑動窗口的格子周期劃分的越多,滑動窗口滾動就越平滑。滑動窗口算法雖然解決了固定窗口的臨界問題,但一旦達到限流后,請求都會直接暴力被拒絕的。對于C端產品來說,這可能不是一種友好的選擇。

三、解決方案

在介紹完目前主流的限流算法及其優缺點之后,讓我們探討一個實際場景:接口提供方已設定限流策略(限流算法為令牌桶算法),而接口調用方在整點前后實施了降級措施(暫不考慮降級是否必要)。在降級恢復時,我們注意到突發流量在第一秒內超過了預設的限流閾值。

前面已經對令牌桶算法有了深入的講解,這里超出限流閾值的原因就不在過多介紹,接下來講講解決方案。

3.1 計算閾值

限流閾值再怎么設置,總會出現由于所有請求都是消耗資源很多的請求可能導致應用承受不住負載而崩潰。那如何計算閾值呢?總體上思路有幾個,看服務的觀測數據、借鑒、手動計算、壓測。

看服務的性能數據屬于常規解法,如基于完善的監控查看峰值期間的QPS。不過我個人覺得,最好的方式應該是線上執行全鏈路壓測,選擇響應時間穩定不變對應的壓測QPS。

盡管設置了限流閾值,但仍然可能出現由于所有請求都消耗大量資源而導致應用負載過高并崩潰的情況。針對這種情況,我們可以采用以下幾種方法來計算閾值:

  1. 借鑒:參考類似服務的閾值設置經驗。
  2. 手動計算:根據業務需求和預期負載進行估算。
  3. 線上執行全鏈路壓測:這是最理想的解決方案,通過選擇響應時間穩定不變的壓測QPS,能夠更準確地評估系統的承載能力。

當然,基于完善的監控系統觀察服務的性能數據也是常規的解決方法,例如查看峰值期間的QPS。然而,我認為線上執行全鏈路壓測是最佳的選擇,因為它能直接模擬真實環境下的負載情況,從而得出更加精確的閾值。

3.2 選擇限流算法

選擇適當的限流算法需要根據具體的應用場景和需求進行評估。例如,對于注重歷史流量參考價值的場景,滑動窗口算法可能更為適用;而對于需要平滑流量的場景,則更適合使用漏桶算法;而對于既要平滑流量又需要處理突發流量的場景,令牌桶算法則可能是最佳選擇。

對于上面提供的場景,令牌桶算法與滑動窗口算法都是可選擇的,只不過前者需要自身應用應對突發流量,而后者在流量超出最大閾值時直接拒絕。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21943.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21943.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21943.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++命名空間(詳解)

C基礎語法 C基于C語言的改進:c在C語言的基礎上引入并擴充了面向對象的概念 C基礎概念:C是基于C語言而產生的,它即可以進行C語言的過程化程序設計,又可以進行以抽象數據類型為特點的基于對象的程序設計,還可以進行面向對象的程序設計 在1998年 出現C98…

愛普生差分晶振在光模塊中的重要角色

光模塊是現代通信設備中的重要組成部分,主要用于實現光電轉換和信號傳輸,它是一種將光信號轉換為電信號,或者將電信號轉換為光信號的設備。在光纖通信中,光模塊扮演著至關重要的角色。 光模塊的主要組成部分包括光源、光接收器、…

OSPF學習筆記(狀態機)

1、鄰居關系 OSPF設備啟動后,會通過OSPF接口向外發送Hello報文,收到Hello報文的OSPF設備會檢查報文中所定義的參數,如果雙方一致就會形成鄰居關系,兩端設備互為鄰居 2、鄰接關系 形成鄰居關系后,如果兩端設備成功交…

【代碼隨想錄】【算法訓練營】【第27天】 [39]組合總和 [40] 組合總和II [131]分割回文串

前言 思路及算法思維,指路 代碼隨想錄。 題目來自 LeetCode。 day26, 休息的周末~ day 27,周一,庫存沒了,哭死~ 題目詳情 [39] 組合總和 題目描述 39 組合總和 解題思路 前提:組合的子集問題&…

C# :IQueryable IEnumerable

文章目錄 1. IEnumerable2. IQueryable3. LINQ to SQL4. IEnumerable & IQueryable4.1 Expression4.2 Provider 1. IEnumerable namespace System.Collections: public interface IEnumerable {public IEnumerator GetEnumerator (); }public interface IEnumerator {pubi…

氣泡式水位計施工技術要求

1、氣泡式水位計壓力氣管出氣口應安裝并固定在最低水位處,其壓力氣管也應固定,有條件的可用金屬管或塑料管保護。氣泡式水位計安裝示意圖見附圖。 2、安裝要求 1)檢查氣泡式水位計氣管外觀有無破損及變形; 2)旋開帶有…

面試數據庫八股文十問十答第十期

面試數據庫八股文十問十答第十期 作者:程序員小白條,個人博客 相信看了本文后,對你的面試是有一定幫助的!關注專欄后就能收到持續更新! ?點贊?收藏?不迷路!? 1)為什么不推薦多表Join&…

特征工程技巧—Bert

前段時間在參加比賽,發現有一些比賽上公開的代碼,其中的數據預處理步驟值得我們參考。 平常我們見到的都是數據預處理,現在我們來講一下特征工程跟數據預處理的區別。 數據預處理是指對原始數據進行清洗、轉換、縮放等操作,以便為…

Blackwell未來發展之路究竟如何?

英偉達Blackwell如何重塑AI計算的未來? 前言 臺灣大學演講 就在6月2日,英偉達CEO黃仁勛在中國臺灣大學綜合體育館發表了最新的演講。這次黃仁勛的演講依舊重磅,更值得注意的是這次演講中還透露了Blackwell今后的發展之路。 介紹Blackwell 介紹…

MongoDB CRUD操作:地理位置查詢

MongoDB CRUD操作:地理位置查詢 文章目錄 MongoDB CRUD操作:地理位置查詢地理空間數據GeoJSON對象傳統坐標對通過數組指定(首選)通過嵌入文檔指定 地理空間索引2dsphere2d 地理空間查詢地理空間查詢運算符地理空間聚合階段 地理空…

拿筆記下來!產品采購制造類合同怎樣寫比較穩妥?

拿筆記下來!產品采購制造類合同怎樣寫比較穩妥? 近日,幾經波折,泰中兩國終于完成了潛艇采購談判!你知道嗎?產品制造類合同或協議在起草前如果沒有充分考慮各種因素,可能會導致一系列問題和不利…

C語言學習:數據類型

一、 為什么要引入數據類型 ? 計算機中每個字節都有一個地址(類似門牌號) ? CPU通過 地址 來訪問這個字節的空間 0x20001103 1 0 0 1 0 0 1 1 0x20001102 1 1 1 0 1 1 1 0 0x20001101 1 1 1 1 0 1 0 1 0x20001100 0 …

linux c socket編程里SO_REUSEADDR的作用

比如下面的代碼 int reuse 1; int ret setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)); if (ret SOCKET_ERROR) {log_error("_SetReuseAddr failed, err_code%d, fd%d", _GetErrorCode(), fd); }代碼解釋 setsockopt 函數用于設置…

無人監控視頻輸出卡頓狀態

設計思路,如下: 1.通過采集卡將視頻信號輸出到個人PC中 2.PC按設置好的時間,視頻屬性分片保存 3.將步驟2中的視頻,按預處理要求,得到待計算的視頻片段 4.使用SSIM算法計算預處理后的視頻,將計算得到的數據存…

聊天機器人的實踐過程

一、語聊機器人 OpenAI 的爆火,到如今也才一年多的時間,然而在過去的一年中,生成式AI的落地場景幾乎 80%都是 ChatBot 的形式,那么今天這篇文章我們就來聊一下,生成式AI和IM能擦出怎么樣的火花?以及各種場…

p13idea的其他操作

1 導入模塊 錯誤示范: 正確示范: 2 刪除模塊 必須用delete才能刪除干凈,用remove刪了之后還要回到文件里面把它刪除掉

有錢還系統源碼 人人還眾籌還錢模式還貸系統源碼

盈利模式: 1.系統里直推400 2.間推得200 3.升級是隔代匹配200 4.漏單直接設置歸系統 5.九級匹配不到直接歸平臺 有錢還平臺新注冊會員,即新入的負債者要分9次分別資助先來的11名負債者每人200元,這筆資助不是一次性給到對方&#xff0c…

Prism 入門04,導航功能

當前章節,沿用 上一章使用Prism 框架創建的WPF 項目空模板。在上一章節,各個不同的模塊之間能夠進行切換并把內容呈現在主程序的頁面當中(其實是通過在主程序中注冊的區域去發起一個導航的請求,然后跳轉到對應的視圖。也就是實現了導航跳轉功能)。 為什么能實現導航的跳轉?…

Mybatis的一級緩存

緩存 MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定制。MyBatis 3 中的緩存實現的很多改進都已經實現了,使得它更加強大而且易于配置。 Mybatis和Hibernate一樣,也有一級和二級緩存,同樣默認開啟的只有一級緩存,二級緩…

docker-compose安裝多環境apollo

下載數據庫sql文件 https://github.com/apolloconfig/apollo/blob/master/scripts/sql/src/apolloconfigdb.sql https://github.com/apolloconfig/apollo/blob/master/scripts/sql/src/apolloportaldb.sql 創建庫并導入表 #生產環境 mysql> CREATE DATABASE IF NOT EXIS…