• SpringCloud-Hystrix 注解配置Hystrix && 和FeignClient集成 (转)


    注解配置Hystrix (原文:https://blog.csdn.net/chenxyz707/article/details/80913725?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param)

    Hystrix也支持以注解的形式配置。通过@HystrixCommand注解的fallbackMethod属性指定降级方法。groupKeycommandKey默认为方法名

    (当然threadPoolKey不指定时,默认和groupKey一致,所以也是方法名),也可以指定这三个key值,配置文件通过groupKey,commandKey,threadPoolKey使用恰当的配置。

    commandPropertiesthreadPoolProperties是通过@HystrixPropertyname value键值对进行配置。

    @Component
    public class UserAnnotationCommand {
    
        @Autowired
        @Qualifier("lbRestTemplate")
        RestTemplate lbRestTemplate;
    
        @HystrixCommand(fallbackMethod = "timeoutFallback", threadPoolProperties = {
                @HystrixProperty(name = "coreSize", value = "20"),
                @HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")
        }, commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "8000")
        })
        public String timeout() {
            return lbRestTemplate.getForObject("http://user-service/user/timeout", String.class);
        }
    
        public String timeoutFallback() {
            return "timeout 降级";
        }
    
    
        @HystrixCommand(fallbackMethod = "exceptionFallback", threadPoolProperties = {
                @HystrixProperty(name = "coreSize", value = "20"),
                @HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")
        }, commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
        })
        public String exception() {
            return lbRestTemplate.getForObject("http://user-service/user/exception", String.class);
        }
    
        public String exceptionFallback() {
            return "exception 降级";
        }
    }

    查看com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect源码,我们可以看到@HystrixCommand注解配置的方式是使用了AOP动态的生成了一个HystrixInvokable对象,通过调用HystrixInvokable的方法实现了HystrixCommand的功能。

    // 使用AOP让注解的@HystrixCommand生效
    @Aspect
    public class HystrixCommandAspect {
        @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
        public void hystrixCommandAnnotationPointcut() {
        }
        @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
        public void hystrixCollapserAnnotationPointcut() {
        }
    
        @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
        public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
            Method method = getMethodFromTarget(joinPoint);
            /***省略***/
            MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
            MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
            HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
            ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
                    metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
    
            Object result;
            try {
                if (!metaHolder.isObservable()) {
                    result = CommandExecutor.execute(invokable, executionType, metaHolder);
                } else {
                    result = executeObservable(invokable, executionType, metaHolder);
                }
            } catch (HystrixBadRequestException e) {
                throw e.getCause() != null ? e.getCause() : e;
            } catch (HystrixRuntimeException e) {
                throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
            }
            return result;
        }
    }

    同样的为了测试这个配置是否生效我们新增接口:

    @RestController
    @RequestMapping("/user")
    public class UserController {
        @Autowired
        UserAnnotationCommand userAnnotationCommand;
    
        @RequestMapping("/command/annotation/timeout")
        public String commandAnnotationTimeout() {
            return userAnnotationCommand.timeout();
        }
    
        @RequestMapping("/command/annotation/exception")
        public String commandAnnotationException() {
            return userAnnotationCommand.exception();
        }
    }

    和FeignClient集成

    在SpringCloud中Hystrix和Feign的集成十分方便。在客户端我们需要使用@EnableCircuitBreaker启用熔断机制。

    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients(defaultConfiguration = FeignClientsConfiguration.class)
    @EnableCircuitBreaker
    public class WebApplicationStarter {
    
        public static void main(String[] args) {
            SpringApplication.run(WebApplicationStarter.class, args);
        }
    }

    同时application.yml配置文件中开启Hystrix,并进行Hystrix配置。

    # 开启熔断机制
    feign:
      hystrix:
        enabled: true
    
    ribbon:
      # 开启eureka与ribbon的集成
      eureka:
        enabled: true
      # 暂不开启熔断机制
      hystrix:
        enabled: false
      # 配置ribbon默认的超时时间
      ConnectTimeout: 20000
      ReadTimeout: 20000
      # 是否开启重试
      OkToRetryOnAllOperations: true
      # 重试的时候实例切换次数
      MaxAutoRetriesNextServer: 3
      # 每个实例重试次数
      MaxAutoRetries: 2
    
    ## hystrix相关配置
    ## hystrix默认会读取classpath下的config.properties文件,application会覆盖config.properties中的属性
    hystrix:
      threadpool:
        # 指定服务的配置
        user-service:
          coreSize: 20
          maxQueueSize: 200
          queueSizeRejectionThreshold: 3
        # userThreadPool是UserTimeOutCommand中配置的threadPoolKey
        userThreadPool:
          coreSize: 20
          maxQueueSize: 20
          queueSizeRejectionThreshold: 3
        # 这是默认的配置
        default:
          coreSize: 10
          maxQueueSize: 200
          queueSizeRejectionThreshold: 2
      command:
        # 指定feign客户端中具体的方法
        UserService#timeout():
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 20000
        userCommandKey:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 15000
        # 这是默认的配置
        default:
          execution:
            timeout:
              enabled: true
            isolation:
              strategy: THREAD
              thread:
                timeoutInMilliseconds: 15000
                interruptOnTimeout: true
                interruptOnFutureCancel: false
              semaphore:
                maxConcurrentRequests: 2
          fallback:
            enabled: true
            isolation:
              semaphore:
                maxConcurrentRequests: 10
          circuitBreaker:
            enabled: true
            forceOpen: false
            forceClosed: false
            requestVolumeThreshold: 4
            errorThresholdPercentage: 50
            sleepWindowInMilliseconds: 10000
          metrics:
            rollingStats:
              timeInMilliseconds: 5000
              numBuckets: 10
            rollingPercentile:
              enabled: true
              timeInMilliseconds: 60000
              numBuckets: 6
              bucketSize: 100
            healthSnapshot:
              intervalInMilliseconds: 500

    这里为了测试超时接口,所以Ribbon配置的超时时间(20s)大于接口的返回时间(10s),否则在Ribbon超时后将自动重试,直到超过Hystrix的超时时间时返回降级信息。在实际中,Hystrix的超时时间应该大于Ribbon的超时时间*Ribbon的重试次数。

    如果项目中config.propertiesapplication.yml文件中都有Hystrix的配置,对于同一配置项,application.yml中的属性会覆盖config.properties中的属性值。当然使用Java API和注解方式也是优先读取application.yml的配置。

    在这个配置中我们甚至可以指定FeignClient中的某一方法的Hystrix配置。比如上面的配置文件中我们定义了UserServicetimeout()方法的超时时间为20s。
    新增Feign客户端和降级类,降级类必须实现对应的Feign客户端。

    @FeignClient(name="user-service", fallback = UserServiceFallback.class)
    public interface UserService {
    
        @RequestMapping(value = "/user/timeout", method = RequestMethod.GET)
        public String timeout();
    
        @RequestMapping(value = "/user/exception", method = RequestMethod.GET)
        public String exception();
    }
    @Component
    public class UserServiceFallback implements UserService {
    
        @Override
        public String timeout() {
            return "timeout 降级";
        }
    
        @Override
        public String exception() {
            return "exception 降级";
        }
    }
     
  • 相关阅读:
    Vertica 业务用户指定资源池加载数据
    Vertica 数据库知识汇总篇
    Oracle OCP 1Z0-053 Exam Topics
    Oracle 11gR2 RAC修改监听默认端口
    Oracle 11.2.0.4 RAC安装最新PSU补丁
    Openfiler配置RAC共享存储
    ORACLE 11gR2 DG(Physical Standby)日常维护01
    oracle 存储过程 返回结果集
    exception javax.crypto.BadPaddingException: Given final block not properly padded
    plsql 连接oracle数据库的2种方式
  • 原文地址:https://www.cnblogs.com/lshan/p/13724058.html
Copyright © 2020-2023  润新知