轉自https://blog.csdn.net/chunlongyu/article/details/53259014?from=singlemessage
在今天带射,基于SOA的架構已經(jīng)大行其道。伴隨著架構的SOA化循狰,相關聯(lián)的服務熔斷窟社、降級、限流等思想绪钥,也在各種技術講座中頻繁出現(xiàn)灿里。本文將結合Netflix開源的Hystrix框架,對這些思想做一個梳理程腹。
背景
伴隨著業(yè)務復雜性的提高匣吊,系統(tǒng)的不斷拆分,一個面向用戶端的API,其內(nèi)部的RPC調(diào)用層層嵌套色鸳,調(diào)用鏈條可能會非常長社痛。這會造成以下幾個問題:
API接口可用性降低
引用Hystrix官方的一個例子,假設tomcat對外提供的一個application命雀,其內(nèi)部依賴了30個服務蒜哀,每個服務的可用性都很高,為99.99%咏雌。那整個applicatiion的可用性就是:99.99%的30次方 = 99.7%凡怎,即0.3%的失敗率校焦。
這也就意味著赊抖,每1億個請求,有30萬個失斦洹氛雪;按時間來算,就是每個月的故障時間超過2小時耸成。
系統(tǒng)被block
假設一個請求的調(diào)用鏈上面有10個服務报亩,只要這10個服務中有1個超時,就會導致這個請求超時井氢。
更嚴重的弦追,如果該請求的并發(fā)數(shù)很高,所有該請求在短時間內(nèi)都被block(等待超時)花竞,tomcat的所有線程都block在此請求上劲件,導致其他請求沒辦法及時響應。
服務熔斷
為了解決上述問題约急,服務熔斷的思想被提出來零远。類似現(xiàn)實世界中的“保險絲“,當某個異常條件被觸發(fā)厌蔽,直接熔斷整個服務牵辣,而不是一直等到此服務超時。
熔斷的觸發(fā)條件可以依據(jù)不同的場景有所不同奴饮,比如統(tǒng)計一個時間窗口內(nèi)失敗的調(diào)用次數(shù)纬向。
實現(xiàn)原理
實現(xiàn)原理講起來很簡單,其實就是不讓客戶端“裸調(diào)“服務器的rpc接口戴卜,而是在客戶端包裝一層逾条。就在這個包裝層里面,實現(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() {
? ? ? ? //關鍵點:把一個RPC調(diào)用膳帕,封裝在一個HystrixCommand里面
? ? ? ? return "Hello " + name + "!";
? ? }
}
//客戶端調(diào)用:以前是直接調(diào)用遠端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 信號量
缺省的危彩,上面的HystrixCommand是被扔到一個線程中執(zhí)行的攒磨,也就是說,缺省是線程隔離策略汤徽。
還有一種策略就是不搞線程池娩缰,直接在調(diào)用者線程中執(zhí)行,也就是信號量的隔離策略谒府。
關于這2者的詳細區(qū)別拼坎,可以去參見官網(wǎng)痘儡。
熔斷的參數(shù)配置
Hystrix提供了如下的幾個關鍵參數(shù)捌蚊,來對一個熔斷器進行配置:
circuitBreaker.requestVolumeThreshold //滑動窗口的大小,默認為20
circuitBreaker.sleepWindowInMilliseconds //過多長時間奏纪,熔斷器再次檢測是否開啟壳鹤,默認為5000盛龄,即5s鐘
circuitBreaker.errorThresholdPercentage //錯誤率,默認50%
3個參數(shù)放在一起芳誓,所表達的意思就是:
每當20個請求中余舶,有50%失敗時,熔斷器就會打開锹淌,此時再調(diào)用此服務匿值,將會直接返回失敗,不再調(diào)遠程服務赂摆。直到5s鐘之后挟憔,重新檢測該觸發(fā)條件,判斷是否把熔斷器關閉库正,或者繼續(xù)打開曲楚。
服務降級
有了熔斷,就得有降級褥符。所謂降級龙誊,就是當某個服務熔斷之后,服務器將不再被調(diào)用喷楣,此時客戶端可以自己準備一個本地的fallback回調(diào)趟大,返回一個缺省值。
這樣做铣焊,雖然服務水平下降逊朽,但好歹可用,比直接掛掉要強曲伊,當然這也要看適合的業(yè)務場景叽讳。
關于Hystrix中fallback的使用追他,此處不詳述,參見官網(wǎng)岛蚤。
服務限流
限流在日常生活中也很常見邑狸,比如節(jié)假日你去一個旅游景點,為了不把景點撐爆涤妒,管理部門通常會在外面設置攔截单雾,限制景點的進入人數(shù)(等有人出來之后,再放新的人進去)她紫。
對應到計算機中硅堆,比如要搞活動,秒殺等贿讹,通常都會限流渐逃。
說到限流,有個關鍵問題就是:你根據(jù)什么策略進行限制围详?朴乖?
比如在Hystrix中,如果是線程隔離助赞,可以通過線程數(shù) + 隊列大小限制;如果是信號量隔離袁勺,可以設置最大并發(fā)請求數(shù)雹食。
另外一個常見的策略就是根據(jù)QPS限制,比如我知道我調(diào)用的一個db服務期丰,qps是3000群叶,那如果不限制,超過3000钝荡,db就可能被打爆街立。這個時候,我可用在服務端做這個限流邏輯埠通,也可以在客戶端做赎离。
現(xiàn)在一般成熟的RPC框架,都有參數(shù)直接設置這個端辱。
還有一些場景下梁剔,可用限制總數(shù):比如連接數(shù),業(yè)務層面限制“庫存“總量等等舞蔽。荣病。
限流的技術原理 -令牌桶算法
關于限流的原理,相信很多人都聽說過令牌桶算法渗柿,Guava的RateLimiter也已經(jīng)有成熟做法个盆,這個自己去搜索之。
此處想強調(diào)的是,令牌桶算法針對的是限制“速率“颊亮。至于其他限制策略鸡岗,比如限制總數(shù),限制某個業(yè)務量的count值编兄,則要具體業(yè)務場景具體分析轩性。
異步RPC
異步RPC主要目的是提高并發(fā),比如你的接口狠鸳,內(nèi)部調(diào)用了3個服務揣苏,時間分別為T1, T2, T3。如果是順序調(diào)用件舵,則總時間是T1 + T2 + T3卸察;如果并發(fā)調(diào)用,總時間是Max(T1,T2,T3)铅祸。
當然坑质,這里有1個前提條件,這3個調(diào)用直接临梗,互相不依賴涡扼。
同樣,一般成熟的RPC框架盟庞,本身都提高了異步化接口吃沪,F(xiàn)uture或者Callback形式。
同樣什猖,Hystrix也提高了同步調(diào)用票彪、異步調(diào)用方式,此處不再詳述不狮。
總結
服務限流降铸、熔斷、降級摇零、異步RPC是基于SOA的分布式系統(tǒng)中一些常見的基本策略推掸,并且這些策略現(xiàn)在都有成熟的開源框架支持。用好這些策略遂黍,對整個系統(tǒng)的容錯性终佛、穩(wěn)定性有很大幫助