探索Java分布式限流技術
一、概述
1.1 主要解決的問題
- 訪問請求流量遠遠大于服務器的負載,致使服務器宕機,導致整個服務的不可用;-
限流
- 當前服務調用其他服務,其他服務不可用,導致當前服務的調用一直超時,進而當前服務的線程資源耗盡,進而服務宕機,產生服務雪崩。-
服務熔斷【或降級】
1.2 限流定義
通過限制并發(fā)數(shù)或一段時間窗口允許處理的最大連接數(shù)
來保護系統(tǒng),一旦超過設定閾值,對當前請求進行處理。主要的處理方式有:跳轉到錯誤頁面、進入排隊系統(tǒng)或降級
等。本質上,就是損失一部分用戶的可用性,來保證整體的可用性
。
1.3 常見限流規(guī)則
1. QPS或連接數(shù)控制;例如對單個IP的限制、單臺機器的限制、單個服務組的限制或整個機房的限制 2. 傳輸速率:例如資源的下載速度 3. 黑白名單。
1.4 分布式限流
把整個分布式環(huán)境中所有服務器當做一個整體來考量。比如說針對IP的限流,我們限制了1個IP每秒最多10個訪問,不管來自這個IP的請求落在了哪臺機器上,只要是訪問了集群中的服務節(jié)點,那么都會受到限流規(guī)則的制約。必須將限流信息保存在一個中心化的組件上,這樣它就可以獲取到集群中所有機器的訪問狀態(tài),目前有兩個比較主流的限流方案:
網關層限流
:應用在流量入口處;中間件限流
:將限流信息存儲在分布式環(huán)境中某個中間件里(比如Redis緩存),每個組件都可以從這里獲取到當前時刻的流量統(tǒng)計,從而決定是拒絕服務還是放行流量。
二、常用的限流方案
2.1 Guava限流
一種Google研發(fā)的客戶端限流組件,非常輕量級。但僅支持單機限流
。底層是令牌桶限流算法
。
2.2 網關層限流
將系統(tǒng)流量的分布層次抽象成一個簡單的漏斗模型來看。
上面是一個最普通的流量模型,從上到下的路徑依次是:
用戶流量從網關層轉發(fā)到后臺服務后臺服務承接流量,調用緩存獲取數(shù)據緩存中無數(shù)據,則訪問數(shù)據庫
Nginx限流
:
基于IP地址和基于服務器的訪問請求限流并發(fā)量(連接數(shù))限流下行帶寬速率限制
SpringCloud 的GateWay組件
限流。
2.3 中間件限流
方案1: Redis+LUA腳本實現(xiàn)限流:
方案2: Sentinal限流:底層使用滑動窗口算法來限流。
三、常用限流算法
3.1 計數(shù)器限流
概述:
在一定周期內累加訪問次數(shù),當訪問次數(shù)達到閾值時,觸發(fā)限流策略,當進入下一個時間周期時,計算器會清零,重新計數(shù)。適用場景:
短信發(fā)送次數(shù)限制存在問題:
臨界問題,會造成系統(tǒng)的抖動。假設時間周期為1s,閾值為50。開始時間是32s, 32.0-32.8s請求次數(shù)為10,32.8-33s請求次數(shù)為30,33.0-33.2請求次數(shù)為30,33.3-34s請求次數(shù)為30,可以看出在32s和33s時間窗口內都沒有觸發(fā)限流閾值,但在32.8-33.2區(qū)間內超過限流閾值,造成系統(tǒng)的不穩(wěn)定。
3.2 滑動窗口限流
概述:
解決了計數(shù)器限流算法的臨界問題。將固定周期劃分為n個小的時間段,分別在每個時間段內統(tǒng)計請求訪問次數(shù),然后根據時間將窗口向前滑動并刪除過期的時間段,時間段越短統(tǒng)計的越準,很好的解決了臨界問題適用場景:
sentinel底層采用該算法存在問題:
窗口大小選擇以及n大小的選擇。
3.3 令牌桶限流
概述:
對于每一個請求,都需要先從令牌桶中獲取令牌。若獲取不到令牌,觸發(fā)限流策略。系統(tǒng)會以一個恒定速率
向令牌童中放入令牌,令牌中滿了后直接丟棄令牌適用場景:
網絡流量整形和速率限制,適合處理突發(fā)流量
。當突發(fā)流量來的時候,可以直接獲取令牌中所有的令牌進行快速處理。Guava底層就采用該算法存在問題:
雖然可以處理突發(fā)流量,但后臺系統(tǒng)的壓力也會瞬間增大,要合理設置令牌數(shù)量。
3.4 漏桶限流算法
概述
:控制數(shù)據注入網絡的速度。在漏桶內部維護一個容器,這個容器會以恒定速率出水,不論漏桶的流入速度多快,出水的速度是固定
的,消息中間件就利用了該思想。適用場景
:流量平滑存在的問題
:無法處理突發(fā)流量。漏桶的天然特性決定了它不會發(fā)生突發(fā)流量,就算每秒1000個請求到來,那么它對后臺服務輸出的訪問速率永遠恒定。而令牌桶則不同,其特性可以預存
一定量的令牌,因此在應對突發(fā)流量的時候可以在短時間消耗所有令牌,其突發(fā)流量處理效率會比漏桶高,但是導向后臺系統(tǒng)的壓力也會相應增多。
四、Guava流量預熱
4.1 概述
核心思想:
動態(tài)的調整令牌的發(fā)放速度,讓流量變化更加平滑。例如:某個接口設定了100個Request每秒的限流標準,同時使用令牌桶算法做限流。假如當前時間窗口內都沒有Request過來,那么令牌桶中會裝滿100個令牌。如果在下一秒突然涌入100個請求,這些請求會迅速消耗令牌,對服務的瞬時沖擊會比較大。
4.2 預熱模型
其中橫坐標是令牌桶的當前容量,縱坐標是令牌發(fā)放速率。
閑時到忙時的流量轉變:
假定當前我們處于閑時流量階段,沒幾個訪問請求,這時令牌桶是滿的。接著在下一秒突然涌入了10個請求,這些請求開始消耗令牌桶中的令牌。在初始階段,令牌的放行速度比較慢,在第一個令牌被消耗以后,后面的請求要經過3x時間間隔也就是0.3s才會獲取第二塊令牌。隨著令牌桶中令牌數(shù)量被逐漸消耗,當令牌存量下降到最大容量一半的時候(Half位置),令牌放行的速率也會提升,以穩(wěn)定間隔0.1s發(fā)放令牌。流量從忙時轉變?yōu)殚e時:
令牌發(fā)放速率是由快到慢逐漸變化。起始階段的令牌放行間隔是0.1s,隨著令牌桶內令牌逐漸增多,當令牌的存量積累到最大容量的一半后,放行令牌的時間間隔進一步增大為0.3s。
RateLimiter正是通過這種方式來控制令牌發(fā)放的時間間隔,從而使流量的變化更加平滑。
五、Sentinel工作原理
概述:
一款高性能的分布式限流組件,能夠保護微服務架構下的應用程序,實現(xiàn)服務限流和服務降級熔斷等。主要原理
:利用AOP切面
來攔截所有的請求,對請求進行實時計數(shù)、實時統(tǒng)計等,并根據設定的閾值來決定是否放行該請求。主要流程
為:
1. 規(guī)則配置。利用sentinel提供的功能來配置限流規(guī)則,即每分鐘請求的次數(shù)。限流規(guī)則會被加載到內存中,sentinel會利用這些限流規(guī)則進行限流 2. 請求攔截。在程序處理處理之前,sentinel利用AOP切面攔截所有的請求; 3. 統(tǒng)計請求。攔截后,sentinel會對請求進行實時統(tǒng)計,在內存中維護的時間窗口內統(tǒng)計請求qps,響應時間以及異常次數(shù)等; 4. 判斷流量。如果qps超過設定的閾值,則進行限流處理,包括降級等;若調用其他服務的響應時間或異常次數(shù)超過閾值,則直接熔斷服務,不再調用其他服務,返回一個默認的降級值 5. 動態(tài)調整限流。可以在運行期間,sentinel可以修改閾值,刪除規(guī)則等
到此這篇關于探索Java分布式限流技術的文章就介紹到這了,更多相關Java分布式限流內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java+mysql實現(xiàn)學籍管理系統(tǒng)
這篇文章主要為大家詳細介紹了Java+mysql實現(xiàn)學籍管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳
本文主要介紹了Thread.currentThread().getName()?和?this.getName()區(qū)別詳解,TestThread?testThread?=?new?TestThread();2022-02-02