1. 程式人生 > >Hystrix之四種觸發fallback情況的驗證

Hystrix之四種觸發fallback情況的驗證

使用Hystrix時,下面的情況會觸發fallback:

  1. 非HystrixBadRequestException異常:當丟擲HystrixBadRequestException時,呼叫程式可以捕獲異常,此時不會觸發fallback,而其他異常則會觸發fallback,呼叫程式將獲得fallback邏輯的返回結果。
  2. run()/construct()執行超時:執行命令的方法超時,將會觸發fallback。
  3. 熔斷器開啟:當熔斷器處於開啟的狀態,將會觸發fallback。
  4. 執行緒池/訊號量已滿:當執行緒池/訊號量已滿的狀態,將會觸發fallback。

下面對這四種情況做簡單的驗證

  • 首先匯入Maven依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

點選這裡可查詢最新的spring-cloud-starter-hystrix版本

  • 在主程式類中新增@EnableHystrix註解
package com.rambo.hystrixtest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@SpringBootApplication
@EnableHystrix
public class HystrixtestApplication {

    public
static void main(String[] args) { SpringApplication.run(HystrixtestApplication.class, args); } }

1、驗證異常觸發fallback

package com.rambo.hystrixtest.degrade.command;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 異常降級
 * **非HystrixBadRequestException異常:當丟擲HystrixBadRequestException時,
 * **呼叫程式可以捕獲異常,此時不會觸發fallback,而其他異常則會觸發fallback,
 * **呼叫程式將獲得fallback邏輯的返回結果。
 */
public class HelloWorldExceptionCommand extends HystrixCommand<String> {
    private final static Logger logger = LoggerFactory.getLogger(HelloWorldExceptionCommand.class);

    private final int n;

    public HelloWorldExceptionCommand(int n) {
        // 最小配置,指定groupKey
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("helloWorldExceptionGroup")));
        this.n = n;
    }

    @Override
    protected String run() throws Exception {
        logger.info(n + "-HelloWorldExceptionCommand A--> " + Thread.currentThread().getName());
        // 製造異常
        int i = 1 / n;
        // 如果此處異常被捕獲,將不會進入getFallback()
        /*
        try {
            int i = 1 / n;
        } catch (Exception e) {
            logger.error("異常:" + e.getMessage());
        }
        */
        logger.info(n + "-HelloWorldExceptionCommand B--> " + Thread.currentThread().getName());
        return n + "執行成功";
    }

    @Override
    protected String getFallback() {
        logger.error(n + "-異常降級! C--> " + Thread.currentThread().getName());
        return n + "執行失敗";
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            if (i == 3) {
                i = 0;
            }
            HelloWorldExceptionCommand command = new HelloWorldExceptionCommand(i);
            logger.info(command.execute());

            Thread.sleep(1000);
        }
    }
}

執行結果如下:

16:41:22.493 [hystrix-helloWorldExceptionGroup-1] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 0-HelloWorldExceptionCommand A--> hystrix-helloWorldExceptionGroup-1
16:41:22.496 [hystrix-helloWorldExceptionGroup-1] DEBUG com.netflix.hystrix.AbstractCommand - Error executing HystrixCommand.run(). Proceeding to fallback logic ...
java.lang.ArithmeticException: / by zero
	at com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand.run(HelloWorldExceptionCommand.java:29)
	at com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand.run(HelloWorldExceptionCommand.java:14)
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
	at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)
	at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)
	at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)
	at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
16:41:22.500 [hystrix-helloWorldExceptionGroup-1] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 0-異常降級! C--> hystrix-helloWorldExceptionGroup-1
16:41:22.504 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 0執行失敗
16:41:23.505 [hystrix-helloWorldExceptionGroup-2] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 1-HelloWorldExceptionCommand A--> hystrix-helloWorldExceptionGroup-2
16:41:23.505 [hystrix-helloWorldExceptionGroup-2] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 1-HelloWorldExceptionCommand B--> hystrix-helloWorldExceptionGroup-2
16:41:23.506 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 1執行成功
16:41:24.508 [hystrix-helloWorldExceptionGroup-3] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 2-HelloWorldExceptionCommand A--> hystrix-helloWorldExceptionGroup-3
16:41:24.508 [hystrix-helloWorldExceptionGroup-3] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 2-HelloWorldExceptionCommand B--> hystrix-helloWorldExceptionGroup-3
16:41:24.508 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 2執行成功
16:41:25.508 [hystrix-helloWorldExceptionGroup-4] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 0-HelloWorldExceptionCommand A--> hystrix-helloWorldExceptionGroup-4
16:41:25.508 [hystrix-helloWorldExceptionGroup-4] DEBUG com.netflix.hystrix.AbstractCommand - Error executing HystrixCommand.run(). Proceeding to fallback logic ...
java.lang.ArithmeticException: / by zero
	at com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand.run(HelloWorldExceptionCommand.java:29)
	at com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand.run(HelloWorldExceptionCommand.java:14)
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
	at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
	at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
	at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
	at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)
	at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)
	at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)
	at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
16:41:25.508 [hystrix-helloWorldExceptionGroup-4] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 0-異常降級! C--> hystrix-helloWorldExceptionGroup-4
16:41:25.509 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 0執行失敗
16:41:26.511 [hystrix-helloWorldExceptionGroup-5] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 1-HelloWorldExceptionCommand A--> hystrix-helloWorldExceptionGroup-5
16:41:26.511 [hystrix-helloWorldExceptionGroup-5] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 1-HelloWorldExceptionCommand B--> hystrix-helloWorldExceptionGroup-5
16:41:26.511 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldExceptionCommand - 1執行成功

2、驗證超時觸發fallback

package com.rambo.hystrixtest.degrade.command;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 超時降級
 * **run()/construct()執行超時:執行命令的方法超時,將會觸發fallback。
 */
public class HelloWorldTimeoutCommand extends HystrixCommand<String> {
    private final static Logger logger = LoggerFactory.getLogger(HelloWorldTimeoutCommand.class);

    private final int n;

    public HelloWorldTimeoutCommand(int n) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("helloWorldTimeoutGroup"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        /*
                         * execution.isolation.thread.timeoutInMilliseconds
                         * 設定呼叫者等待命令執行的超時限制,超過此時間,HystrixCommand被標記為TIMEOUT,
                         * 並執行回退邏輯。
                         * 預設值:1000(毫秒)
                         */
                        .withExecutionTimeoutInMilliseconds(500)
                        /*
                         * execution.timeout.enabled
                         * 設定HystrixCommand的執行是否有超時限制。
                         * 預設值:true
                         */
                        .withExecutionTimeoutEnabled(true)
                        /*
                         * execution.isolation.thread.interruptOnTimeout
                         * 設定HystrixCommand的執行是否在超時發生時被中斷。
                         * 使用執行緒隔離時,是否對命令執行超時的執行緒呼叫中斷(Thread.interrupt())操作。
                         * 預設值:true
                         */
                        .withExecutionIsolationThreadInterruptOnTimeout(false)
                )
        );
        this.n = n;
    }

    @Override
    protected String run() throws Exception {
        logger.info(n + "-HelloWorldTimeoutCommand A--> " + Thread.currentThread().getName());
        if (n == 0) {
            // 設定超時
            Thread.sleep(1000);
        }
        // 設定withExecutionIsolationThreadInterruptOnTimeout(false)後面程式碼將會繼續執行
        logger.info(n + "-HelloWorldTimeoutCommand B--> " + Thread.currentThread().getName());
        return n + "執行成功";
    }

    @Override
    protected String getFallback() {
        logger.error("超時降級! C--> " + Thread.currentThread().getName());
        return n + "執行失敗";
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            if (i == 5) {
                i = 0;
            }
            HelloWorldTimeoutCommand command = new HelloWorldTimeoutCommand(i);
            // 超時執行getFallback
            logger.info(command.execute());

            Thread.sleep(1000);
        }
    }
}

執行結果如下:

16:09:25.408 [hystrix-helloWorldTimeoutGroup-1] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-1
16:09:25.906 [HystrixTimer-1] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 超時降級! C--> HystrixTimer-1
16:09:25.913 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0執行失敗
16:09:26.410 [hystrix-helloWorldTimeoutGroup-1] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-1
16:09:26.914 [hystrix-helloWorldTimeoutGroup-2] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-2
16:09:26.914 [hystrix-helloWorldTimeoutGroup-2] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-2
16:09:26.914 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1執行成功
16:09:27.915 [hystrix-helloWorldTimeoutGroup-3] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-3
16:09:27.915 [hystrix-helloWorldTimeoutGroup-3] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-3
16:09:27.915 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2執行成功
16:09:28.917 [hystrix-helloWorldTimeoutGroup-4] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-4
16:09:29.418 [HystrixTimer-1] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 超時降級! C--> HystrixTimer-1
16:09:29.419 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0執行失敗
16:09:29.917 [hystrix-helloWorldTimeoutGroup-4] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-4
16:09:30.421 [hystrix-helloWorldTimeoutGroup-5] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-5
16:09:30.421 [hystrix-helloWorldTimeoutGroup-5] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-5
16:09:30.421 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1執行成功
16:09:31.423 [hystrix-helloWorldTimeoutGroup-6] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-6
16:09:31.423 [hystrix-helloWorldTimeoutGroup-6] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-6
16:09:31.423 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2執行成功
16:09:32.425 [hystrix-helloWorldTimeoutGroup-7] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-7
16:09:32.926 [HystrixTimer-4] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 超時降級! C--> HystrixTimer-4
16:09:32.926 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0執行失敗
16:09:33.426 [hystrix-helloWorldTimeoutGroup-7] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-7
16:09:33.927 [hystrix-helloWorldTimeoutGroup-8] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-8
16:09:33.927 [hystrix-helloWorldTimeoutGroup-8] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-8
16:09:33.928 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1執行成功
16:09:34.929 [hystrix-helloWorldTimeoutGroup-9] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-9
16:09:34.929 [hystrix-helloWorldTimeoutGroup-9] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-9
16:09:34.929 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2執行成功
16:09:35.930 [hystrix-helloWorldTimeoutGroup-10] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-10
16:09:36.431 [HystrixTimer-3] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 超時降級! C--> HystrixTimer-3
16:09:36.432 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0執行失敗
16:09:36.930 [hystrix-helloWorldTimeoutGroup-10] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 0-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-10
16:09:37.433 [hystrix-helloWorldTimeoutGroup-10] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-10
16:09:37.433 [hystrix-helloWorldTimeoutGroup-10] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-10
16:09:37.433 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 1執行成功
16:09:38.435 [hystrix-helloWorldTimeoutGroup-10] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand A--> hystrix-helloWorldTimeoutGroup-10
16:09:38.435 [hystrix-helloWorldTimeoutGroup-10] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2-HelloWorldTimeoutCommand B--> hystrix-helloWorldTimeoutGroup-10
16:09:38.435 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldTimeoutCommand - 2執行成功

3、驗證熔斷器開啟觸發fallback

package com.rambo.hystrixtest.degrade.command;

import com.netflix.hystrix.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 觸發熔斷器熔斷
 * **熔斷器開啟:當熔斷器處於開啟的狀態,將會觸發fallback。
 */
public class HelloWorldBreakerCommand extends HystrixCommand<String> {
    private final static Logger logger = LoggerFactory.getLogger(HelloWorldBreakerCommand.class);

    private final int n;

    public HelloWorldBreakerCommand(int n) {
        //最小配置,指定groupKey
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("helloWorldBreakerGroup"))
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                                /*
                                 * execution.isolation.thread.timeoutInMilliseconds
                                 * 設定呼叫者等待命令執行的超時限制,超過此時間,HystrixCommand被標記為TIMEOUT,
                                 * 並執行回退邏輯。
                                 * 預設值:1000(毫秒)
                                 */
                                .withExecutionTimeoutInMilliseconds(1000)
                                /*
                                 * execution.isolation.thread.interruptOnTimeout
                                 * 設定HystrixCommand的執行是否在超時發生時被中斷。
                                 * 使用執行緒隔離時,是否對命令執行超時的執行緒呼叫中斷(Thread.interrupt())操作。
                                 * 預設值:true
                                 */
                                .withExecutionIsolationThreadInterruptOnTimeout(true)
                                // ** 斷路器(Circuit Breaker)屬性配置 **
                                /*
                                 * circuitBreaker.enabled
                                 * 設定斷路器是否生效
                                 * 預設值:true
                                 */
                                .withCircuitBreakerEnabled(true)
                                /*
                                 * circuitBreaker.requestVolumeThreshold
                                 * 設定在一個滾動視窗中,開啟斷路器的最少請求數。比如:如果值是20,在一個視窗內(比如10秒),收到19個請求,即使這19個請求都失敗了,斷路器也不會開啟。
                                 * 預設值:20
                                 */
                                .withCircuitBreakerRequestVolumeThreshold(6)
                                /*
                                 * circuitBreaker.sleepWindowInMilliseconds
                                 * 設定在斷路器被開啟,拒絕請求到再次嘗試請求的時間間隔。
                                 * 預設值:5000(毫秒)
                                 */
                                .withCircuitBreakerSleepWindowInMilliseconds(3000)
                                /*
                                 * circuitBreaker.errorThresholdPercentage
                                 * 設定開啟斷路器並啟動回退邏輯的錯誤比率。
                                 * (這個引數的效果受到circuitBreaker.requestVolumeThreshold和滾動時間視窗的時間長度影響)
                                 * 預設值:50(%)
                                 */
                                .withCircuitBreakerErrorThresholdPercentage(50)
                )
                //設定核心執行緒池的大小
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(20))
        );
        this.n = n;
    }

    @Override
    protected String run() throws Exception {
        logger.info(n + "-HelloWorldTimeoutCommand A--> " + Thread.currentThread().getName());
        if (n > 0) {
            // 設定超時
            Thread.sleep(1000);
        }
        // 設定withExecutionIsolationThreadInterruptOnTimeout(true)後面程式碼將中斷執行
        logger.info(n + "-HelloWorldTimeoutCommand B--> " + Thread.currentThread().getName());
        return n + "執行成功";
    }

    @Override
    protected String getFallback() {
        logger.error("熔斷降級! C--> " + Thread.currentThread().getName());
        return n + "執行失敗";
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            try {
                if (i == 10) {
                    i = 0;
                    Thread.sleep(1000);
                }
                logger.info(new HelloWorldBreakerCommand(i).execute());
            } catch (Exception e) {
                logger.error("異常:" + e.getMessage(), e);
            }
        }
    }
}

執行結果如下:

16:35:36.190 [hystrix-helloWorldBreakerGroup-1] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 0-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-1
16:35:36.190 [hystrix-helloWorldBreakerGroup-1] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 0-HelloWorldTimeoutCommand B--> hystrix-helloWorldBreakerGroup-1
16:35:36.193 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 0執行成功
16:35:36.194 [hystrix-helloWorldBreakerGroup-2] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 1-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-2
16:35:37.195 [hystrix-helloWorldBreakerGroup-2] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 1-HelloWorldTimeoutCommand B--> hystrix-helloWorldBreakerGroup-2
16:35:37.201 [HystrixTimer-1] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> HystrixTimer-1
16:35:37.202 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 1執行失敗
16:35:37.203 [hystrix-helloWorldBreakerGroup-3] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 2-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-3
16:35:38.203 [hystrix-helloWorldBreakerGroup-3] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 2-HelloWorldTimeoutCommand B--> hystrix-helloWorldBreakerGroup-3
16:35:38.203 [HystrixTimer-2] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> HystrixTimer-2
16:35:38.204 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 2執行失敗
16:35:38.205 [hystrix-helloWorldBreakerGroup-4] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 3-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-4
16:35:39.205 [HystrixTimer-1] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> HystrixTimer-1
16:35:39.205 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 3執行失敗
16:35:39.206 [hystrix-helloWorldBreakerGroup-5] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 4-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-5
16:35:40.206 [hystrix-helloWorldBreakerGroup-5] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 4-HelloWorldTimeoutCommand B--> hystrix-helloWorldBreakerGroup-5
16:35:40.206 [HystrixTimer-3] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> HystrixTimer-3
16:35:40.206 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 4執行失敗
16:35:40.207 [hystrix-helloWorldBreakerGroup-6] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 5-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-6
16:35:41.207 [hystrix-helloWorldBreakerGroup-6] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 5-HelloWorldTimeoutCommand B--> hystrix-helloWorldBreakerGroup-6
16:35:41.207 [HystrixTimer-2] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> HystrixTimer-2
16:35:41.208 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 5執行失敗
16:35:41.209 [hystrix-helloWorldBreakerGroup-7] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 6-HelloWorldTimeoutCommand A--> hystrix-helloWorldBreakerGroup-7
16:35:42.210 [hystrix-helloWorldBreakerGroup-7] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 6-HelloWorldTimeoutCommand B--> hystrix-helloWorldBreakerGroup-7
16:35:42.211 [HystrixTimer-4] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> HystrixTimer-4
16:35:42.212 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 6執行失敗
16:35:42.213 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:42.213 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 7執行失敗
16:35:42.213 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:42.214 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 8執行失敗
16:35:42.214 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:42.214 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 9執行失敗
16:35:43.215 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.215 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 0執行失敗
16:35:43.215 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.215 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 1執行失敗
16:35:43.216 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.216 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 2執行失敗
16:35:43.216 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.216 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 3執行失敗
16:35:43.216 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.216 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 4執行失敗
16:35:43.216 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.216 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 5執行失敗
16:35:43.216 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.216 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 6執行失敗
16:35:43.216 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.216 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 7執行失敗
16:35:43.217 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.217 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 8執行失敗
16:35:43.217 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:43.217 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 9執行失敗
16:35:44.218 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:44.218 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 0執行失敗
16:35:44.218 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:44.218 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 1執行失敗
16:35:44.218 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:44.218 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 2執行失敗
16:35:44.218 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:44.218 [main] INFO com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 3執行失敗
16:35:44.218 [main] ERROR com.rambo.hystrixtest.degrade.command.HelloWorldBreakerCommand - 熔斷降級! C--> main
16:35:44.218 [main] INFO com.rambo.hys