天天看點

springcloud-hystrix容錯保護注解方式的使用

簡單的搭建的流程:第一,eureka注冊中心;第二,在eureka上注冊的服務;第三,在eureka消費服務的用戶端,hystrix,是在用戶端上的使用,在調用端嵌入jar包,以jar包的方式使用hystrix,不需要額外的安裝,在項目中添加如下依賴。

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

@EnableCircuitBreaker或@EnableHystrix開啟hystrix的使用,由于這是在服務調用端的添加,是以一般還需要添加@EnableDiscoveryClient注解,還可以使用@SpringCloudApplication,進去這個注解可以發現這個注解包括以下注解,是以@SpringCloudApplication注解可以使用hystrix

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
           

hystrix提供5部分的服務,分别是降級、隔離、熔斷器、異常和緩存,對于緩存,個人認為是雞肋的功能,在這裡不做說明。在網上看到很多使用代碼的方式進行降級等操作,個人認為并不好,這些屬于非功能的業務使用注解的方式會更好,是以在這裡主要介紹注解的方式。

降級:

/**
         * 同步的方式實作
         * @return
         */
        @HystrixCommand(fallbackMethod = "fallback")
        public String consumer() {
            return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
        }
		
		/**
         * 異步的方式實作
         * @return
         */
        @HystrixCommand(
                commandProperties = {
                        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="40000"),
                }
        )
        public Future<String> consumerA(){
            return new AsyncResult<String>() {
                @Override
                public String invoke() {
                    return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
                }
            };
        }
		
	public String fallback() {
            return "fallbck";
        }
           

有兩種實作的方式,一種同步一種異步,當服務調用失敗的時候,便會直接調用fallback方法,異步需要調用端按照以下方式處理才能擷取相關資料

Future<String> result = consumerService.consumerA();
        return result.get();
           

降級處理的時候可以連續降級,fallback方法是可以繼續使用HystrixCommand指令指定降級方法,直到處理完畢

隔離:

/**
         * @return
         */
        @HystrixCommand(
                //表示所屬的group,一個group共用線程池,預設使用類名作為一個組,
				//同一個分組,使用相同的線程池,線程池的個數按照最小的定義限定,是以線程池定義一次就可以了,再次使用的時候直接定義分組
                //同一個分組,不同的線程池,按照不同的線程池來限定
                groupKey = "GroupOne",
                //線程池的名稱
                threadPoolKey = "groupOnePoolE",
                fallbackMethod = "fallbackTest",
                commandProperties = {
                        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="20000"),
                },
                //以下這些值,在分組的情況下有效
                threadPoolProperties = {
                        //核心線程數
                        @HystrixProperty(name = "coreSize", value = "3"),
                        //超過隊列的個數會直接失敗
                        @HystrixProperty(name = "maxQueueSize", value = "10"),
                        //隊列小于最大值,拒絕請求
                        @HystrixProperty(name = "queueSizeRejectionThreshold", value = "3")
                        //總結:請求數目大于核心線程數+隊列的拒絕數的時候就會失敗,配置降級方法的時候,不會失敗直接調用降級方法
                        //預設的情況下,以service的名稱作為線程池的名稱,使用HystrixCommand預設情況下coreSize為10,maxQueueSize使用LinkedBlockingQueue動态拓展,queueSizeRejectionThreshold預設大小值5
                }
        )
        public String consumerPN() {
            try{
                Thread.sleep(10000);
            }catch (Exception e){


            }
            return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
        }


        public String fallbackTest(){
            return "十次使用者請求并發後,超過設定會觸發這個降級,否則會出現失敗頁面";
        }
		
           

熔斷器:

@HystrixCommand(
                commandProperties = {
                        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="11000"),
                        //是否開啟熔斷器
                        @HystrixProperty(name = "circuitBreaker.enabled", value ="true"),
                        //請求的失敗數目超過這個之後,就會打開熔斷器
                        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value ="5"),
                        //熔斷器工作時間,預設5秒,超過這個時間便會放流量進去
                        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value ="50000"),
                        //出錯率超過75%,啟動熔斷器,預設50%
                        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value ="75"),
                }
        )
        public String fuse() {
            try{
                Thread.sleep(10000);
            }catch (Exception e){


            }
            return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
        }
           

異常:

/**
         * 以下方式抛出RuntimeException異常的時候不會降級,而是直接按照異常進行處理,将異常抛給調用端
         * 如果沒有在ignoreExceptions中添加RuntimeException,則會将異常按照降級方法進行處理
         * @return
         */
        @HystrixCommand(ignoreExceptions = {RuntimeException.class},fallbackMethod = "fallback")
        public String consumerAT() {
            String result = null;
            try {
                result = restTemplate.getForObject("http://add?a=10&b=20", String.class);
            }catch (Exception e){
                throw new RuntimeException();
            }
            return result;
        }
           

繼續閱讀