限流,熔斷,降級(jí)

轉(zhuǎn)自https://blog.csdn.net/chunlongyu/article/details/53259014?from=singlemessage

在今天,基于SOA的架構(gòu)已經(jīng)大行其道。伴隨著架構(gòu)的SOA化,相關(guān)聯(lián)的服務(wù)熔斷、降級(jí)、限流等思想,也在各種技術(shù)講座中頻繁出現(xiàn)。本文將結(jié)合Netflix開源的Hystrix框架,對(duì)這些思想做一個(gè)梳理。

背景

伴隨著業(yè)務(wù)復(fù)雜性的提高,系統(tǒng)的不斷拆分,一個(gè)面向用戶端的API,其內(nèi)部的RPC調(diào)用層層嵌套,調(diào)用鏈條可能會(huì)非常長(zhǎng)。這會(huì)造成以下幾個(gè)問題:

API接口可用性降低

引用Hystrix官方的一個(gè)例子,假設(shè)tomcat對(duì)外提供的一個(gè)application,其內(nèi)部依賴了30個(gè)服務(wù),每個(gè)服務(wù)的可用性都很高,為99.99%。那整個(gè)applicatiion的可用性就是:99.99%的30次方 = 99.7%,即0.3%的失敗率。

這也就意味著,每1億個(gè)請(qǐng)求,有30萬(wàn)個(gè)失敗;按時(shí)間來算,就是每個(gè)月的故障時(shí)間超過2小時(shí)。

系統(tǒng)被block

假設(shè)一個(gè)請(qǐng)求的調(diào)用鏈上面有10個(gè)服務(wù),只要這10個(gè)服務(wù)中有1個(gè)超時(shí),就會(huì)導(dǎo)致這個(gè)請(qǐng)求超時(shí)。

更嚴(yán)重的,如果該請(qǐng)求的并發(fā)數(shù)很高,所有該請(qǐng)求在短時(shí)間內(nèi)都被block(等待超時(shí)),tomcat的所有線程都block在此請(qǐng)求上,導(dǎo)致其他請(qǐng)求沒辦法及時(shí)響應(yīng)。

服務(wù)熔斷

為了解決上述問題,服務(wù)熔斷的思想被提出來。類似現(xiàn)實(shí)世界中的“保險(xiǎn)絲“,當(dāng)某個(gè)異常條件被觸發(fā),直接熔斷整個(gè)服務(wù),而不是一直等到此服務(wù)超時(shí)。

熔斷的觸發(fā)條件可以依據(jù)不同的場(chǎng)景有所不同,比如統(tǒng)計(jì)一個(gè)時(shí)間窗口內(nèi)失敗的調(diào)用次數(shù)。

實(shí)現(xiàn)原理

實(shí)現(xiàn)原理講起來很簡(jiǎn)單,其實(shí)就是不讓客戶端“裸調(diào)“服務(wù)器的rpc接口,而是在客戶端包裝一層。就在這個(gè)包裝層里面,實(shí)現(xiàn)熔斷邏輯。

拿Hystrix的helloword舉例:

public class CommandHelloWorld extends HystrixCommand<String> {

? ? private final String name;

? ? public CommandHelloWorld(String name) {

? ? ? ? super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));

? ? ? ? this.name = name;

? ? }

? ? @Override

? ? protected String run() {

? ? ? ? //關(guān)鍵點(diǎn):把一個(gè)RPC調(diào)用,封裝在一個(gè)HystrixCommand里面

? ? ? ? return "Hello " + name + "!";

? ? }

}

//客戶端調(diào)用:以前是直接調(diào)用遠(yuǎn)端RPC接口,現(xiàn)在是把RPC接口封裝到HystrixCommand里面,它內(nèi)部完成熔斷邏輯

String s = new CommandHelloWorld("World").execute();

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

隔離策略: 線程 vs 信號(hào)量

缺省的,上面的HystrixCommand是被扔到一個(gè)線程中執(zhí)行的,也就是說,缺省是線程隔離策略。

還有一種策略就是不搞線程池,直接在調(diào)用者線程中執(zhí)行,也就是信號(hào)量的隔離策略。

關(guān)于這2者的詳細(xì)區(qū)別,可以去參見官網(wǎng)。

熔斷的參數(shù)配置

Hystrix提供了如下的幾個(gè)關(guān)鍵參數(shù),來對(duì)一個(gè)熔斷器進(jìn)行配置:

circuitBreaker.requestVolumeThreshold //滑動(dòng)窗口的大小,默認(rèn)為20

circuitBreaker.sleepWindowInMilliseconds //過多長(zhǎng)時(shí)間,熔斷器再次檢測(cè)是否開啟,默認(rèn)為5000,即5s鐘

circuitBreaker.errorThresholdPercentage //錯(cuò)誤率,默認(rèn)50%

3個(gè)參數(shù)放在一起,所表達(dá)的意思就是:

每當(dāng)20個(gè)請(qǐng)求中,有50%失敗時(shí),熔斷器就會(huì)打開,此時(shí)再調(diào)用此服務(wù),將會(huì)直接返回失敗,不再調(diào)遠(yuǎn)程服務(wù)。直到5s鐘之后,重新檢測(cè)該觸發(fā)條件,判斷是否把熔斷器關(guān)閉,或者繼續(xù)打開。

服務(wù)降級(jí)

有了熔斷,就得有降級(jí)。所謂降級(jí),就是當(dāng)某個(gè)服務(wù)熔斷之后,服務(wù)器將不再被調(diào)用,此時(shí)客戶端可以自己準(zhǔn)備一個(gè)本地的fallback回調(diào),返回一個(gè)缺省值。

這樣做,雖然服務(wù)水平下降,但好歹可用,比直接掛掉要強(qiáng),當(dāng)然這也要看適合的業(yè)務(wù)場(chǎng)景。

關(guān)于Hystrix中fallback的使用,此處不詳述,參見官網(wǎng)。

服務(wù)限流

限流在日常生活中也很常見,比如節(jié)假日你去一個(gè)旅游景點(diǎn),為了不把景點(diǎn)撐爆,管理部門通常會(huì)在外面設(shè)置攔截,限制景點(diǎn)的進(jìn)入人數(shù)(等有人出來之后,再放新的人進(jìn)去)。

對(duì)應(yīng)到計(jì)算機(jī)中,比如要搞活動(dòng),秒殺等,通常都會(huì)限流。

說到限流,有個(gè)關(guān)鍵問題就是:你根據(jù)什么策略進(jìn)行限制??

比如在Hystrix中,如果是線程隔離,可以通過線程數(shù) + 隊(duì)列大小限制;如果是信號(hào)量隔離,可以設(shè)置最大并發(fā)請(qǐng)求數(shù)。

另外一個(gè)常見的策略就是根據(jù)QPS限制,比如我知道我調(diào)用的一個(gè)db服務(wù),qps是3000,那如果不限制,超過3000,db就可能被打爆。這個(gè)時(shí)候,我可用在服務(wù)端做這個(gè)限流邏輯,也可以在客戶端做。

現(xiàn)在一般成熟的RPC框架,都有參數(shù)直接設(shè)置這個(gè)。

還有一些場(chǎng)景下,可用限制總數(shù):比如連接數(shù),業(yè)務(wù)層面限制“庫(kù)存“總量等等。。

限流的技術(shù)原理 -令牌桶算法

關(guān)于限流的原理,相信很多人都聽說過令牌桶算法,Guava的RateLimiter也已經(jīng)有成熟做法,這個(gè)自己去搜索之。

此處想強(qiáng)調(diào)的是,令牌桶算法針對(duì)的是限制“速率“。至于其他限制策略,比如限制總數(shù),限制某個(gè)業(yè)務(wù)量的count值,則要具體業(yè)務(wù)場(chǎng)景具體分析。

異步RPC

異步RPC主要目的是提高并發(fā),比如你的接口,內(nèi)部調(diào)用了3個(gè)服務(wù),時(shí)間分別為T1, T2, T3。如果是順序調(diào)用,則總時(shí)間是T1 + T2 + T3;如果并發(fā)調(diào)用,總時(shí)間是Max(T1,T2,T3)。

當(dāng)然,這里有1個(gè)前提條件,這3個(gè)調(diào)用直接,互相不依賴。

同樣,一般成熟的RPC框架,本身都提高了異步化接口,F(xiàn)uture或者Callback形式。

同樣,Hystrix也提高了同步調(diào)用、異步調(diào)用方式,此處不再詳述。

總結(jié)

服務(wù)限流、熔斷、降級(jí)、異步RPC是基于SOA的分布式系統(tǒng)中一些常見的基本策略,并且這些策略現(xiàn)在都有成熟的開源框架支持。用好這些策略,對(duì)整個(gè)系統(tǒng)的容錯(cuò)性、穩(wěn)定性有很大幫助

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容