跳閘了啊! 服務容災:熔斷器簡介

雪崩效應

現現在SOA、微服務風愈演愈烈,愈來愈多的業務和資源被以服務的形式包裝和發佈,服務間又可能會依賴其餘各類服務。由此而來不可避免的會產生不少問題。html

好比一個服務,其依賴了另外30個服務。假設每一個服務的可用率都有三個9(99.9%),那麼咱們計算一下:前端

99.99%^30 = 99.7%nginx

現實很殘酷,這個服務的實際可用性只能是99.7%,也就是說每月這個服務都要好宕機8000+秒~~~git


正經常使用戶請求時,服務內部依次請求A\P\H\I服務,兵返回響應結果。github


很是不幸,咱們的I服務出了某些問題,此時咱們的用戶請求就被堵塞在I服務處。spring


更加悲劇的是,後續愈來愈多的請求都被堵塞在I服務處,而這些被堵塞的請求會佔用線程、IO、網絡等系統資源,隨着資源被佔用的愈來愈多,原本不存在的性能問題也會隨之而來,形成系統中的其餘服務出現問題,甚至致使系統奔潰。docker

這也就是咱們常說的雪崩效應緩存


服務容災

爲了不出現服務的雪崩,咱們須要對服務作容災處理。服務器

常規的服務容災處理思路有:網絡

  • 資源隔離
  • 超時設定
  • 服務降級
  • 服務限流

其中每種思路又能夠有不一樣的解決方案。

好比資源隔離能夠經過將不一樣的服務發佈在獨立的docker容器或服務器中,這樣即便一個服務出現問題,也不會殃及池魚。

服務降級和服務限流能夠經過前端nginx+lua來實現,當服務處理延遲或宕機時,nginx能夠直接返回固定的降級/失敗響應,已快速跳過問題服務。


Hystrix

Hystrix,是Netflix的一個開源熔斷器,經過Hystrix,咱們能夠很方便的實現資源隔離、限流、超時設計、服務降級等服務容災措施,而且還提供了強大的監控,能夠查看各個熔斷器的容許狀況。

經過上圖,能夠看出,Hystrix提供了一個HystrixCommand用來包裝調用請求。HystrixCommand的執行流程大概以下:
1.首先檢查緩存中是否有結果。若是有則直接返回緩存結果。
2.判斷斷路器是否開啓,若是斷路器閉合,執行降級業務邏輯並返回降級結果。
3.判斷信號量/線程池資源是否飽和,如飽和則執行降級業務邏輯並返回降級結果。
4.調用實際服務,如發生異常,執行降級業務邏輯並返回降級結果,並調整斷路器閾值。
5.判斷實際業務是否超時,超時則返回超時響應結果,並調整斷路器閾值。

瞭解了流程,來看下如何使用Hystrix。首先咱們須要定義一個命令類來包裝咱們的業務調用:

//繼承HystrixCommand
public class CommandHelloFailure extends HystrixCommand<String> {

    private final String name;

    public CommandHelloFailure(String name) {
        //設置分組key,分組key能夠用在報表、監控中,默認的線程池隔離也基於分組key
         super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
            //指定命令key,可
            .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"))
            //指定線程池key,取代默認的分組key
            .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")));
        /*
        //線程池隔離模式,不寫默認是線程池隔離模式
        HystrixCommandProperties.Setter()
           .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)
        //信號量隔離模式
        HystrixCommandProperties.Setter()
           .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
        //超時時間,默認1秒
        HystrixCommandProperties.Setter()
           .withExecutionTimeoutInMilliseconds(int value)  
        //信號量模式下,最大併發請求限流,默認值10
        HystrixCommandProperties.Setter()
           .withFallbackIsolationSemaphoreMaxConcurrentRequests(int value)  
        //熔斷器閾值,默認20
        HystrixCommandProperties.Setter()
            .withCircuitBreakerRequestVolumeThreshold(int value)
        //熔斷器關閉時間,默認5秒
        HystrixCommandProperties.Setter()
            .withCircuitBreakerSleepWindowInMilliseconds(int value)
        */
        this.name = name;
    }

    @Override
    //執行實際服務,這裏模擬所有返回異常
    protected String run() {
        throw new RuntimeException("this command always fails");
    }

    @Override
    //執行降級業務
    protected String getFallback() {
        return "Hello Failure " + name + "!";
    }

    @Override
    //從緩存中獲取
    protected String getCacheKey() {
        ...
    }
}

使用這個命令類也很是簡單:

//同步執行
String s = new CommandHelloWorld("Bob").execute();
//異步執行
Future<String> s = new CommandHelloWorld("Bob").queue();
//響應式
Observable<String> s = new CommandHelloWorld("Bob").observe();

經過Hystrix提供的監控界面,咱們能夠觀察到各個熔斷器的執行狀況:

更多說明和例子能夠查看Hystrix的wiki


Hystrix和Spring boot

想在spring boot中使用Hystrix就更加簡單了,只須要引入spring-cloud-starter-hystrix,

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

而後添加註解使用Hystrix
@EnableCircuitBreaker
@EnableHystrixDashboard

最後在須要使用熔斷器的地方標記註解便可。

@HystrixCommand(groupKey = "xxx", fallbackMethod = "yyy")
public String doSomething()

遙想2015年9月7日,上交所、深交所、中金所宣佈,擬在保留現有個股漲跌幅制度前提下,引入指數熔斷機制。隨後A股聯繫兩天下跌熔斷,提早收盤。其中這裏的熔斷機制和咱們今天討論的熔斷器思路一致,可是反而致使了A股暴跌,這也說明了咱們仍是得從根源產出高可用的服務,而不是依賴某些外部措施幫助咱們提升可用性。同時說明了A股比咱寫的垃圾服務更加不可靠,仍是安心當個碼農吧。

最後,就問各位童鞋,敢不敢點個贊~~~~

參考資料: https://github.com/Netflix/Hystrix http://www.cnblogs.com/jesse2013/p/things-architect-must-know.html

相關文章
相關標籤/搜索