Hystrix 工作流程


Hystrix是如何處理請求,在官網有詳細介紹:https://github.com/Netflix/Hystrix/wiki/How-it-Works, 本文重點圍繞下方流程圖介紹一下主要的流程;

Hystrix是將我們的系統間調用包裝成一個個Comman來執行,舉個簡單的例子:

public class TestCommand extends HystrixCommand<Integer> {

    private TestServiceA serviceA;

    private int index;

    private static HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
                                                                                    //至少有10個請求,熔斷器才進行錯誤率的計算
                                                                                    .withCircuitBreakerRequestVolumeThreshold(3)
                                                                                    //熔斷器中斷請求5秒后會進入半打開狀態,放部分流量過去重試
                                                                                    .withCircuitBreakerSleepWindowInMilliseconds(5000)
                                                                                    //錯誤率達到50開啟熔斷保護
//                                                                                    .withCircuitBreakerErrorThresholdPercentage(30)
                                                                                    .withExecutionIsolationSemaphoreMaxConcurrentRequests(2)
                                                                                    .withExecutionTimeoutEnabled(true)
                                                                                    .withExecutionTimeoutInMilliseconds(1000);

    protected TestCommand(TestServiceA serviceA, int index) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("testGroupKey"))
                    .andCommandKey(HystrixCommandKey.Factory.asKey("testCommandKey"))
                    .andCommandPropertiesDefaults(setter)
                    .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10)));
        this.serviceA = serviceA;
        this.index = index;
    }

    @Override
    protected Integer run() throws Exception {
        return serviceA.service(index);
    }

    @Override
    protected Integer getFallback() {
        // if service execute fail, do sth
        return -1;
    }

}

// execute
TestCommand testCommand = new TestCommand(new TestServiceA(), i);
testCommand.execute();

 我們只需要用一個Command來包裝我們的RPC/RMI調用,上面就使用 TestCommand 包裝了一個TestService 方法;

 下面解釋流程圖中具體邏輯;

1、包裝請求:

 可以使用繼承HystrixCommand或HystrixObservableCommand來包裝業務方法;

2、發起請求:

 使用調用Command的execute來執行一個業務方法調用;

 Hystrix除了提供了execute方法,另外還提供了3種方來,所有的請求入口:

  

K             value   = command.execute();
Future<K>     fValue  = command.queue();
Observable<K> ohValue = command.observe();         //hot observable
Observable<K> ocValue = command.toObservable();    //cold observable

  如上圖所示:

  執行同步調用execute方法,會調用queue().get()方法,queue()又會調用toObservable().toBlocking().toFuture();

  所以,所有的方法調用都依賴Observable的方法調用,只是取決於是需要同步還是異步調用;

3、緩存處理:

  當請求來到后,會判斷請求是否啟用了緩存(默認是啟用的),再判斷當前請求是否攜帶了緩存Key;

  如果命中緩存就直接返回;否則進入剩下的邏輯;

4、判斷斷路器是否打開(熔斷):

  斷路器是Hystrix的設計核心,斷路器是實現快速失敗的重要手段(斷路器打開就直接返回失敗);

  可以設置斷路器打開一定時間后,可以進行嘗試進行業務請求(默認是5000毫秒);

5、判斷是否進行業務請求(請求是否需要隔離或降級):

  是否進行業務請求之前還會根據當前服務處理質量,判斷是否需要去請求業務服務;

  如果當前服務質量較低(線程池/隊列/信號量已滿),那么也會直接失敗;

  線程池或信號量的選擇(默認是線程池):

    線程池主要優勢是客戶端隔離和超時設置,但是如果是海量低延遲請求時,頻繁的線程切換帶來的損耗也是很可觀的,這種情況我們就可以使用信號量的策略;

    信號量的主要缺點就是不能處理超時,請求發送到客戶端后,如果被客戶端pending住,那么就需要一直等待;

6、執行業務請求:

  當前服務質量較好,那么就會提交請求到業務服務器去;

  HystrixObservableCommand.construct() or HystrixCommand.run()

7、健康監測:

  根據歷史的業務方法執行結果,來統計當前的服務健康指標,為斷路器是否熔斷等動作作為依據;  

8/9、響應失敗或成功的處理結果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM