服务熔断、降级、限流、异步RPC -- HyStrix
本人新書出版,對技術感興趣的朋友請關注:
https://mp.weixin.qq.com/s/uq2cw2Lgf-s4nPHJ4WH4aw
在今天,基于SOA的架構已經大行其道。伴隨著架構的SOA化,相關聯的服務熔斷、降級、限流等思想,也在各種技術講座中頻繁出現。本文將結合Netflix開源的Hystrix框架,對這些思想做一個梳理。
背景
伴隨著業務復雜性的提高,系統的不斷拆分,一個面向用戶端的API,其內部的RPC調用層層嵌套,調用鏈條可能會非常長。這會造成以下幾個問題:
API接口可用性降低
引用Hystrix官方的一個例子,假設tomcat對外提供的一個application,其內部依賴了30個服務,每個服務的可用性都很高,為99.99%。那整個applicatiion的可用性就是:99.99%的30次方 = 99.7%,即0.3%的失敗率。
這也就意味著,每1億個請求,有30萬個失敗;按時間來算,就是每個月的故障時間超過2小時。
系統被block
假設一個請求的調用鏈上面有10個服務,只要這10個服務中有1個超時,就會導致這個請求超時。
更嚴重的,如果該請求的并發數很高,所有該請求在短時間內都被block(等待超時),tomcat的所有線程都block在此請求上,導致其他請求沒辦法及時響應。
服務熔斷
為了解決上述問題,服務熔斷的思想被提出來。類似現實世界中的“保險絲“,當某個異常條件被觸發,直接熔斷整個服務,而不是一直等到此服務超時。
熔斷的觸發條件可以依據不同的場景有所不同,比如統計一個時間窗口內失敗的調用次數。
實現原理
實現原理講起來很簡單,其實就是不讓客戶端“裸調“服務器的rpc接口,而是在客戶端包裝一層。就在這個包裝層里面,實現熔斷邏輯。
拿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調用,封裝在一個HystrixCommand里面
? ? ? ? return "Hello " + name + "!";
? ? }
}
//客戶端調用:以前是直接調用遠端RPC接口,現在是把RPC接口封裝到HystrixCommand里面,它內部完成熔斷邏輯
String s = new CommandHelloWorld("World").execute();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
隔離策略: 線程 vs 信號量
缺省的,上面的HystrixCommand是被扔到一個線程中執行的,也就是說,缺省是線程隔離策略。
還有一種策略就是不搞線程池,直接在調用者線程中執行,也就是信號量的隔離策略。
關于這2者的詳細區別,可以去參見官網。
熔斷的參數配置
Hystrix提供了如下的幾個關鍵參數,來對一個熔斷器進行配置:
circuitBreaker.requestVolumeThreshold //滑動窗口的大小,默認為20
circuitBreaker.sleepWindowInMilliseconds //過多長時間,熔斷器再次檢測是否開啟,默認為5000,即5s鐘
circuitBreaker.errorThresholdPercentage //錯誤率,默認50%
3個參數放在一起,所表達的意思就是:
每當20個請求中,有50%失敗時,熔斷器就會打開,此時再調用此服務,將會直接返回失敗,不再調遠程服務。直到5s鐘之后,重新檢測該觸發條件,判斷是否把熔斷器關閉,或者繼續打開。
服務降級
有了熔斷,就得有降級。所謂降級,就是當某個服務熔斷之后,服務器將不再被調用,此時客戶端可以自己準備一個本地的fallback回調,返回一個缺省值。
這樣做,雖然服務水平下降,但好歹可用,比直接掛掉要強,當然這也要看適合的業務場景。
關于Hystrix中fallback的使用,此處不詳述,參見官網。
服務限流
限流在日常生活中也很常見,比如節假日你去一個旅游景點,為了不把景點撐爆,管理部門通常會在外面設置攔截,限制景點的進入人數(等有人出來之后,再放新的人進去)。
對應到計算機中,比如要搞活動,秒殺等,通常都會限流。
說到限流,有個關鍵問題就是:你根據什么策略進行限制??
比如在Hystrix中,如果是線程隔離,可以通過線程數 + 隊列大小限制;如果是信號量隔離,可以設置最大并發請求數。
另外一個常見的策略就是根據QPS限制,比如我知道我調用的一個db服務,qps是3000,那如果不限制,超過3000,db就可能被打爆。這個時候,我可用在服務端做這個限流邏輯,也可以在客戶端做。
現在一般成熟的RPC框架,都有參數直接設置這個。
還有一些場景下,可用限制總數:比如連接數,業務層面限制“庫存“總量等等。。
限流的技術原理 -令牌桶算法
關于限流的原理,相信很多人都聽說過令牌桶算法,Guava的RateLimiter也已經有成熟做法,這個自己去搜索之。
此處想強調的是,令牌桶算法針對的是限制“速率“。至于其他限制策略,比如限制總數,限制某個業務量的count值,則要具體業務場景具體分析。
異步RPC
異步RPC主要目的是提高并發,比如你的接口,內部調用了3個服務,時間分別為T1, T2, T3。如果是順序調用,則總時間是T1 + T2 + T3;如果并發調用,總時間是Max(T1,T2,T3)。
當然,這里有1個前提條件,這3個調用直接,互相不依賴。
同樣,一般成熟的RPC框架,本身都提高了異步化接口,Future或者Callback形式。
同樣,Hystrix也提高了同步調用、異步調用方式,此處不再詳述。
總結
服務限流、熔斷、降級、異步RPC是基于SOA的分布式系統中一些常見的基本策略,并且這些策略現在都有成熟的開源框架支持。用好這些策略,對整個系統的容錯性、穩定性有很大幫助。
#后話
有興趣朋友可以關注公眾號“架構之道與術”, 獲取最新文章和進一步討論。
---------------------?
作者:travi?
來源:CSDN?
原文:https://blog.csdn.net/chunlongyu/article/details/53259014?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的服务熔断、降级、限流、异步RPC -- HyStrix的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “我是技术总监,你干嘛总问我技术细节?”
- 下一篇: 谈谈我对服务熔断、服务降级的理解