柏竹 柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档

柏竹

奋斗柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档
  • Java基础

  • JavaWeb

  • 拓展技术

  • 框架技术

  • 数据库

  • 数据结构

  • Spring

  • SpringMVC

  • SpringBoot

  • SpringClound

    • SpringCloud认知
    • SpringCloud Eureka注册中心
    • SpringCloud Ribbon负载均衡
    • SpringCloud Hystrix熔断器
      • 雪崩效应
      • 线程隔离&服务降级
        • 示例
        • 超时设置
      • 熔断器
        • 示例
        • 配置熔断策略
    • SpringCloud Feign
    • SpringCloud Gateway网关
    • SpringCloud Config配置中心
    • SpringCloud Bus服务总线
  • Ruoyi-Vue-Plus

  • 后端
  • SpringClound
柏竹
2021-10-19
目录

SpringCloud Hystrix熔断器

# Hystrix 熔断器

Hystrix 是一个用于分布式系统的 ==延迟==、==容错== 的开源库。在分布式系统里,许多依赖不可避免的调用失败,比如超时、异常等。==Hystrix能够保证在一个依赖出问题的情况下,不会导致整个服务失败==,避免级联故障,以提高分布式系统的弹性。

Hystrix 能为系统做:

  • 保护并控制通过第三方客户库访问的 延迟 和 故障(通常是通过网络访问的依赖关系)
  • 停止复杂分布式系统中的级联故障
  • 失败快速和快速恢复
  • 回退,并尽可能优雅地降级
  • 实现近实时监控、警报和操作控制

# 雪崩效应

在 分布式系统 中通常有多个服务进行调用,这一高并发的过程难免会有故障的时候,消费者一旦请求出现故障,请求会被堵塞,tomcat不会释放该线程,于是请求越来越多,最终导致服务器资源耗尽,形成了雪崩效应

提供者E 突然发生故障,导致线程堵塞

# 线程隔离&服务降级

线程隔离:将请求资源用 ==线程池== 进行隔离,如果线程池已满,将不进行排队,直接判定为失败

服务降级:请求失败,会返回失败的提示(如 :对不起,网络太拥堵了 请求服务降级有以下两种的情况

  1. 被分配到已满的线程池
  2. 请求超时(超时时长自行配置

# 示例

代码在上篇文章的基础上进行添加编辑:Java学习记录 03Spring Cloud 负载均衡Ribbon (opens new window)

  1. 消费者 添加依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  2. 消费者 启动类 ,添加注解 @EnableCircuitBreaker

    // @EnableDiscoveryClient // Eureka客户端
    // @EnableCircuitBreaker  // 熔断器
    // @SpringBootApplication
    // 该注解组合以上3个注解
    @SpringCloudApplication
    public class ConsumerApplication {
        // ....
    }
    

    @SpringCloudApplication 注解整合了 Eureka、Hystrix、启动器 注解

  3. 消费者 服务降级处理 ,controller

    降级处理有两种方式:

    方式 注解 用于 优点
    1 @HystrixCommand(fallbackMethod = "{降级服务的方法名}") 方法 降级服务的方法可获取方法的参数
    2 @DefaultProperties(defaultFallback = "{降级服务的方法名}") 类、接口、枚举、Annotation类型 可统一降级服务,降低维护成本
    @RestController
    @RequestMapping("consumer")
    @Slf4j
    // 方式2.1 多接口响应
    @DefaultProperties (defaultFallback = "defaultFallback")
    public class ConsumerController {
        
        @Autowired
        private RestTemplate restTemplate;
        
        //...
        
        @RequestMapping("{id}")
        // 方式1.1 单个接口响应
        // @HystrixCommand(fallbackMethod = "queryByIdFallback")
        // 方式2.2
        @HystrixCommand
        public String findById(@PathVariable Long id) throws InterruptedException {
            String url = "HTTP://user-service/user/"+id;
            return restTemplate.getForObject(url , String.class);
        }
        
        // 方式1.2(方式1有参数接收,因 方式1 写在方法里!
        public String queryByIdFallback(Long id) {
            log.error("查询信息失败1,id : {}",id);
            return "对不起,网络太拥堵了!(Test1";
        }
        
        // 方式2.3
        public String defaultFallback() {
            log.error("查询信息失败2");
            return "对不起,网络太拥挤了!(Test2";
        }
        
    }
    

    修改了 findById()方法 的返回值,从 提供者 那获取也是json格式,为了也方便降级数据的返回,因此返回值为String

  4. 测试

    1. 依次打开 Eureka、server、consumer 三个服务
    2. 访问 http://localhost:8080/consumer/1 (返回 数据
    3. 关闭 server 再次访问以上请求
    4. 页面返回:"对不起,网络太拥挤了!(Test2 " (成功降级服务处理

# 超时设置

  1. 消费者 application.yml ,添加超时配置

    # 请求超过2s回返回错误,默认1s(测试用
    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000
    
  2. 提供者 controller 休眠 (只为触发超时 休眠写 被调用服务的方法里

    @RequestMapping("{id}")
    public User findById(@PathVariable Long id) {
        /* 
           测试 : 超时请求延迟 
           识别判断:保留1为小数
        */
        Thread.sleep(2000);
        // Thread.sleep(1900);
        return service.findById(id);
    }
    
  3. 测试

    1. 依次打开 Eureka、server、consumer 三个服务
    2. 打开浏览器F12 检查请求的时长,访问 http://localhost:8080/consumer/1 (返回 数据
    3. 休眠2s返回结果:"对不起,网络太拥挤了!(Test2 " (成功降级服务处理
    4. 休眠1.9s返回结果:数据

# 熔断器

熔断器它会在一段时间内检测请求异常,如果末段时间内异常超出一定比例时,则迫使请求进行 降级服务 ,并非 调用提供者,从而防止更多请求发生同样的失败操作。一旦触发熔断器打开,需要等待休眠,休眠结束后会释放少部分请求进行测试,如果还是出现问题,则继续打开熔断器,否则关闭熔断器

日常例子:

好比家用的漏电开关,一旦电压不稳定,就打开电闸,断开电源

熔断器计算 出来的状态分别有:

  • Closed (关闭):所有请求正常访问
  • Open (打开):所有请求降级服务
  • Half-Open (半打开):当打开的熔断器休眠结束后,会释放部分请求,如果都是健康,就关闭熔断器,否则保持打开熔断器

熔断器的 默认配置&触发条件:

  • 最小请求次数 20次
  • 异常比例阈值 50%
  • 熔断休眠时长 5s

解释:5s内访问次数20次,如果超过10次的是异常,则打开熔断器 休眠5s

# 示例

在以上代码的基础上进行编辑

  1. 消费者 controller 制造异常 (上面的 Hystrix依赖 也要有!!!)

    @RequestMapping("{id}")
    @HystrixCommand
    public String findById(@PathVariable Long id) throws InterruptedException {
    
        // 测试 :异常制造 (实现熔断器报错预期
        if (id == 1) {
            throw new RuntimeException("忙碌");
        }
        
       	//..
        
        String url = "HTTP://user-service/user/"+id;
        
        return restTemplate.getForObject(url , String.class);
    }
    

    注意:上面测试代码,如果打开有休眠,先清空添加的休眠代码

  2. 测试 流程:先访问 ==请求1== 20+次 (制造异常触发熔断器),然后在访问 ==请求2== (访问失败)

    1. 触发阈值的请求:http://localhost:8080/consumer/1 (注定失败
    2. 测试熔断的请求:http://localhost:8080/consumer/2 (测试熔断

    熔断器的触发条件上面说有,就不赘述了

# 配置熔断策略

修改熔断器的 默认配置:

# 熔断触发最小请求次数,默认值是20
hystrix.command.default.circuitBreaker.requestVolumeThreshold=10
# 熔断后休眠时长,默认值5000ms
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=10000
# 触发熔断错误比例阈值,默认值50%
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
# 请求超过2s回返回错误,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000

以上配置可自行尝试调用


仓库代码 : https://gitee.com/Bozhu12/spring-cloud-examples.git (opens new window)

#SpringClound#Java

← SpringCloud Ribbon负载均衡 SpringCloud Feign→

最近更新
01
HTTPS自动续签
10-21
02
博客搭建-简化版(脚本)
10-20
03
ruoyi-vue-plus-部署篇
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2024 | 桂ICP备2022009417号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式