天天看点

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;
        }
           

继续阅读