Hystrix基础之服务降级演示

前言

  • 本次服务降级主要演示的是:服务提供者和服务调用者两端的降级演示

环境准备

  • EurekaServer集群 搭建地址
  • 服务提供者hystrix-client8011
  • 服务调用者 hystrix-feign-client80

服务提供者降级

  • 创建hystrix-client8011:(SpringBoot项目的创建这里不做介绍)

  • 更改POM文件

        <dependencies>
            <!--   引入hystrix依赖包     -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!--必须添加的依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--非必须,它的作用用于监控以及健康检查-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
        </dependencies>
    
  • 添加application.yml

    server:
      port: 8011 #端口号
    spring:
      application:
        name: hystrix-client-service #服务名称
    eureka:
      client:
        serviceUrl:
          defaultZone: http://eurekaServer8761.com:8761/eureka/,http://eurekaServer8762.com:8762/eureka/ #eurekaServer集群地址
      instance:
        instance-id: service8011
        prefer-ip-address: true
    
  • 添加主启动类

    /**
     * 主启动类
     * @EnableEurekaClient:开启Eureka客户端组件
     * @EnableCircuitBreaker:开启Hystrix组件
     */
    @SpringBootApplication
    @EnableEurekaClient
    @EnableCircuitBreaker
    public class HystrixClientMain8011 {
    
        public static void main(String[] args) {
            SpringApplication.run(HystrixClientMain8011.class,args);
        }
    }
    
  • 提供接口及实现类

    public interface UserServiceInter {
    
        String success(String userId);
    
        String timeOut(String userId);
    
    }
    
    
    @Service
    public class UserServiceInterImpl implements UserServiceInter {
    
        @Override
        public String success(String userId) {
    
            return "执行成功!";
        }
    
    	/**
         * @HystrixCommand:对接口进行降级的注解
         * fallbackMethod:指定降级方法
         * commandProperties:用于配置降级属性,多个属性用逗号分隔
         * @HystrixProperty:降级属性的注解
         *  name:属性名称,这里以超时为例
         *  value:最大超时时间,执行时间大于等于它时直接降级
         */
        @HystrixCommand(fallbackMethod = "fallbackTimeOut",
                        commandProperties = {
                            @HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",
                                             value = "2000")
        })
        @Override
        public String timeOut(String userId) {
    
            try {
                TimeUnit.MILLISECONDS.sleep(3000);
                return "执行成功,耗时三秒钟!";
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         *降级方法
         */
        public String fallbackTimeOut(String userId){
    
            return "hystrix-client8011:服务器忙请稍后再试!userId="+userId;
        }
    
    }
    
    
  • 编写Controller

    @RestController
    @Slf4j
    public class TestController {
    
        @Value("${server.port}")
        private String port;
    
        @Autowired
        private UserServiceInter userServiceInter;
    
        @GetMapping(value = "service/success/{userId}")
        public String success(@PathVariable("userId") String userId){
            return userServiceInter.success(userId);
        }
    
        @GetMapping(value = "service/timeOut/{userId}")
        public String timeOut(@PathVariable("userId") String userId){
            return userServiceInter.timeOut(userId);
        }
    }
    
  • 访问:http://127.0.0.1:8011/service/timeOut/123,可以看到降级的方法执行了
    在这里插入图片描述

服务调用者客户端降级

  • 创建hystrix-feign-client80:(SpringBoot项目的创建这里不做介绍)

  • 更改POM文件

    <dependencies>
    
            <!--   hystrix核心依赖     -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
            <!--openfeign依赖,用于调用服务提供者-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
            <!--eureka依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <!--必须添加的依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--非必须,它的作用用于监控以及健康检查-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
        </dependencies>
    
    
  • 添加application.yml

    server:
      port: 80 #端口号
    spring:
      application:
        name: hystrix-feign-client-consumption #服务名称(消费者)
    eureka:
      client:
        serviceUrl:
          defaultZone: http://eurekaServer8761.com:8761/eureka/,http://eurekaServer8762.com:8762/eureka/
    
    ribbon:
      ReadTimeout: 5000 #建立连接所用的时间,指的是两端连接的时间设置5秒钟
      ConnectTimeout: 5000 #建立连接后从服务器读取到资源所用的时间设置5秒钟
    
    feign:
      hystrix:
        enabled: true #开启hystrix的支持
    
    logging:
      level:
        com.dwj.springcloud.service.UserServiceInter: debug #feign日志以debug级别监控与服务提供者绑定的接口
    
    
  • 添加主启动类

    
    /**
     * @EnableFeignClients:开启OpenFeign
     * @EnableHystrix:开启Hystrix组件
     */
    @SpringBootApplication
    @EnableFeignClients
    @EnableHystrix 
    public class HystrixFeignClientMain80 {
    
        public static void main(String[] args) {
            SpringApplication.run(HystrixFeignClientMain80.class,args);
        }
    }
    
  • 新建接口,使用OpenFeign完成对服务提供者的接口绑定,可参考OpenFeign基本介绍

    @Component
    @FeignClient(value = "HYSTRIX-CLIENT-SERVICE")
    public interface UserServiceInter {
    
        @GetMapping(value = "service/success/{userId}")
        String success(@PathVariable("userId") String userId);
    
        @GetMapping(value = "service/timeOut/{userId}")
        String timeOut(@PathVariable("userId") String userId);
    }
    
  • 编写Controller

    @RestController
    @Slf4j
    public class TestController {
    
        @Value("${server.port}")
        private String port;
    
        @Autowired
        private UserServiceInter userServiceInter;
    
        @GetMapping(value = "consumption/success/{userId}")
        public String success(@PathVariable("userId") String userId){
    
           return userServiceInter.success(userId);
    
        }
    
    
        /**
         *设置最大超时时间为一秒钟,当服务接口响应时间大于等于一秒钟时直接降级
         */
        @HystrixCommand(fallbackMethod = "timeOutFallback",
                        commandProperties = {
                            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
                                             value = "1000")
        })
        @GetMapping(value = "consumption/timeOut/{userId}")
        public String timeOut(@PathVariable("userId") String userId){
    
            return userServiceInter.timeOut(userId);
        }
    
        /**
         *降级方法
         */
        public String timeOutFallback(@PathVariable("userId") String userId){
    
            return "hystrix-feign-client80:客户端繁忙请稍后再试userId="+userId;
    
        }
    }
    
  • 修改服务提供者hystrix-client8011的降级时间,最大超时时间为五秒钟,方法执行时间为三秒钟所以该服务接口正常

        /**
         * @HystrixCommand:对接口进行降级的注解
         * fallbackMethod:指定降级方法
         * commandProperties:用于配置降级属性,多个属性用逗号分隔
         * @HystrixProperty:降级属性的注解
         *  name:属性名称,这里以超时为例
         *  value:最大超时时间,执行时间大于等于它时直接降级
         */
        @HystrixCommand(fallbackMethod = "fallbackTimeOut",
                        commandProperties = {
                            @HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",
                                             value = "5000")
        })
        @Override
        public String timeOut(String userId) {
    
            try {
                TimeUnit.MILLISECONDS.sleep(3000);
                return "执行成功,耗时三秒钟!";
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
  • 访问:http://127.0.0.1/consumption/timeOut/1234,服务提供者接口正常,但调用者客户端自己最大超时时间是一秒钟,所以直接降级
    在这里插入图片描述

  • 注意:在实际服务调用中,一般都是调用者客户端进行降级,很少出现客户端和服务端都降级的情况这里只做演示

全局服务降级

  • 上面虽然实现了服务降级,但是如果一个类中有多个方法都需要超时降级,那岂不是要在每个方法头上写@HystrixCommand降级配置

  • 解决方案:@DefaultProperties

    /**
     * @DefaultProperties:针对本类的全局降级注解
     * defaultFallback:默认全局降级方法
     */
    @RestController
    @Slf4j
    @DefaultProperties(defaultFallback = "defaultFallback",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
                            value = "1000")
            })
    public class TestController {
    
        @Value("${server.port}")
        private String port;
    
        @Autowired
        private UserServiceInter userServiceInter;
    
        @GetMapping(value = "consumption/success/{userId}")
        public String success(@PathVariable("userId") String userId){
    
           return userServiceInter.success(userId);
    
        }
    
        @HystrixCommand
        @GetMapping(value = "consumption/timeOut/{userId}")
        public String timeOut(@PathVariable("userId") String userId){
    
            return userServiceInter.timeOut(userId);
        }
    
        /**
         *降级方法
         */
        public String defaultFallback(){
    
            return "hystrix-feign-client80:客户端繁忙请稍后再试";
    
        }
    }
    
  • 全局降级以后一个类只需要配置一次降级属性,如果需要针对某个方法进行自定义降级处理,再单独定义即可

  • 强调一点:上面虽然配置的是对超时进行降级,但是如果程序出现运行时异常、服务宕机也一样会走降级的方法

通用服务降级

  • 虽然全局服务降级可以节省部分代码量,但是降级的逻辑和我们的业务代码耦合度太高

  • 解决方法:在OpenFeign的接口绑定上增加fallback属性

    /**
     * fallback:降级类的字节码文件,该类实现了本接口,故完成对每个接口方法的降级
     */
    @Component
    @FeignClient(value = "HYSTRIX-CLIENT-SERVICE",fallback = UserServiceFallback.class)
    public interface UserServiceInter {
    
        @GetMapping(value = "service/success/{userId}")
        String success(@PathVariable("userId") String userId);
    
        @GetMapping(value = "service/timeOut/{userId}")
        String timeOut(@PathVariable("userId") String userId);
    
    }
    
    
    
    @Component
    public class UserServiceFallback implements UserServiceInter {
    
        @Override
        public String success(String userId) {
            return "hystrix-feign-client80:客户端繁忙请稍后再试,success方法";
        }
    
        @Override
        public String timeOut(String userId) {
            return "hystrix-feign-client80:客户端繁忙请稍后再试,timeOut方法";
    
        }
    
    }
    
    
  • 客户端Controller代码恢复

    @RestController
    @Slf4j
    public class TestController {
    
        @Value("${server.port}")
        private String port;
    
        @Autowired
        private UserServiceInter userServiceInter;
    
        @GetMapping(value = "consumption/success/{userId}")
        public String success(@PathVariable("userId") String userId){
    
           return userServiceInter.success(userId);
    
        }
    
        @GetMapping(value = "consumption/timeOut/{userId}")
        public String timeOut(@PathVariable("userId") String userId){
    
            return userServiceInter.timeOut(userId);
        }
    
    }
    
  • 修改hystrix-client8011的接口实现类

    @Service
    public class UserServiceInterImpl implements UserServiceInter {
    
        @Override
        public String success(String userId) {
    
            /**
             * 模拟一个运行时异常
             */
            int i = 10/0; 
    
            return "执行成功!";
        }
    
    
  • 访问:http://127.0.0.1/consumption/success/123,客户端直接降级
    在这里插入图片描述
    本文只是Hystrix服务降级简单入门,如有错误请各位读者及时提出。以上案列均参考尚硅谷周阳老师B站视频

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值