• SpringCloud系列---【Hystrix熔断器】


    一、熔断器作用

    Hystrix是Netflflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库、防止出现级联失败也就
    是雪崩效应。
    二、工作原理

     服务的健康状况 = 请求失败数 / 请求总数. 

    熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.

    1. 当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态.

    2. 当熔断器开关打开时, 请求被禁止通过.

    3. 当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过.

    熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.

    三、使用示例

    1.引入依赖

    <!--熔断Hystrix starter--> 
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

    2.开启熔断的注解

    //注解简化写法:微服务中,注解往往引入多个,简化注解可以使用组合注解。@SpringCloudApplication =等同于@SpringBootApplication+@EnableDiscoveryClient+@EnableCircuitBreaker
    @SpringBootApplication
    @EnableDiscoveryClient//开启服务发现
    @EnableCircuitBreaker//开启熔断
    public class ConsumerApplication {
        @Bean
        @LoadBalanced//开启负载均衡
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class,args);
        }
    }

    3.编写服务降级处理方法:使用@HystrixCommand定义fallback方法。

    @RequestMapping("{id}")
    @HystrixCommand(fallbackMethod ="queryByIdFallback")
    public String queryById(@PathVariable Long id){
        String url = String.format("http://user-service/user/%d", id);
        return restTemplate.getForObject(url,String.class);
    }
    
    public String queryByIdFallback(Long id){
        return "对不起,网络太拥挤了!";
    }

    4.配置熔断策略

    1. 常见熔断策略配置

    2. 熔断后休眠时间:sleepWindowInMilliseconds

    3. 熔断触发最小请求次数:requestVolumeThreshold

    4. 熔断触发错误比例阈值:errorThresholdPercentage

    5. 熔断超时时间:timeoutInMilliseconds

    # 配置熔断策略:
    hystrix:
      command:
        default:
          circuitBreaker:
            # 原理分析中解释配置含义
            # 强制打开熔断器 默认false关闭的。测试配置是否生效
            forceOpen: false
            # 触发熔断错误比例阈值,默认值50%
            errorThresholdPercentage: 50
            # 熔断后休眠时长,默认值5秒
            sleepWindowInMilliseconds: 5000
            # 熔断触发最小请求次数,默认值是20
            requestVolumeThreshold: 10
          execution:
            isolation:
              thread:
                # 熔断超时设置,默认为1秒
                timeoutInMilliseconds: 2000

    5.模拟异常代码

    @GetMapping("{id}")
    @HystrixCommand(fallbackMethod ="queryByIdFallback")
    public String queryById(@PathVariable Long id){
        //如果参数为1抛出异常,否则 执行REST请求返回user对象
        if (id == 1){
            throw new RuntimeException("too busy!!!");
        }
        String url = String.format("http://user-service/user/%d", id);
        return restTemplate.getForObject(url,String.class);
    }

    6.测试熔断的情况(==模拟请求超时==):

        访问超时:服务提供者线程休眠超过2秒,访问消费者触发fallback方法。

    @Service
    public class UserService {
        @Autowired
        private UserMapper userMapper;
        
        public User queryById(Long id){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return userMapper.selectByPrimaryKey(id);
        }
    }

        服务不可用:停止user-service服务提供者。访问消费者触发fallback方法。

    7.

    ==什么时候熔断:==

    1. 访问超时

    2. 服务不可用(死了)

    3. 服务抛出异常(虽然有异常但还活着)

    4. 其他请求导致服务异常到达阈值,所有服务都会被降级

      扩展-服务降级的fallback方法:

      <!--注意:因为熔断的降级逻辑方法跟正常逻辑方法一样,必须保证相同的参数列表和返回值相同-->

      两种编写方式:编写在类上,编写在方法上。在类的上边对类的所有方法都生效。在方法上,仅对当前方法有效。

      1. 方法上服务降级的fallback兜底方法

        • 使用HystrixCommon注解,定义

        • @HystrixCommand(fallbackMethod="queryByIdFallBack")用来声明一个降级逻辑的fallback兜底方法

      2. 类上默认服务降级的fallback兜底方法

        • 刚才把fallback写在了某个业务方法上,如果方法很多,可以将FallBack配置加在类上,实现默认FallBack

        • @DefaultProperties(defaultFallback=”defaultFallBack“),在类上,指明统一的失败降级方法;

          @RestController
          @RequestMapping("/consumer")
          @DefaultProperties(defaultFallback = "defaultFallback")//开启默认的FallBack,统一失败降级方法(兜底)
          public class ConsumerController {
              @GetMapping("{id}")
              @HystrixCommand
              public String queryById(@PathVariable Long id){
                  //如果参数为1抛出异常,否则 执行REST请求返回user对象
                  if (id == 1){
                      throw new RuntimeException("too busy!!!");
                  }
                  String url = String.format("http://user-service/user/%d", id);
                  return restTemplate.getForObject(url,String.class);
              }
              /**
               * queryById的降级方法
               */
              public String queryByIdFallback(Long id){
             return "对不起,网络太拥挤了!";
              }
              /**
               * 默认降级方法
               */
              public String defaultFallback(){
                  return "默认提示:对不起,网络太拥挤了!";
              }
          }
    愿你走出半生,归来仍是少年!
  • 相关阅读:
    银联支付集成之 ---- 安卓
    在Mac系统下配置PHP运行环境
    ios工程中一天只让显示一次的广告,或是弹出窗,如何实现
    iOS工程中一天只让进行一次的操作如何做?
    简单实现UIlabel可复制功能
    iOS添加测试设备与调试
    iOS-最全的App上架教程
    javaIO--文件操作类
    javaIO--字符流
    javaIO--字节流
  • 原文地址:https://www.cnblogs.com/hujunwei/p/13088683.html
Copyright © 2020-2023  润新知