【四】Hystrix熔断降级

由Netflix开源的⼀个延迟和容错库,⽤于隔离访问远程系统、服务或者第三⽅库,防⽌级联失败,从⽽提升系统的可⽤性与容错性

上篇【三】spring cloud 构建服务端和客户端ribbon

Hystrix简介

Hystrix主要通过以下⼏点实现延迟和容错。
包裹请求:使⽤HystrixCommand包裹对依赖的调⽤逻辑。
(@HystrixCommand 添加Hystrix控制) ——调⽤简历微服务
跳闸机制:当某服务的错误率超过⼀定的阈值时,Hystrix可以跳闸,停⽌请求该服务⼀段时间。
资源隔离:Hystrix为每个依赖都维护了⼀个⼩型的线程池(舱壁模式)(或者信号量)。如果该线程池已满, 发往该依赖的请求就被⽴即拒绝,⽽不是排队等待,从⽽加速失败判定。
监控:Hystrix可以近乎实时地监控运⾏指标和配置的变化,例如成功、失败、超时、以及被拒绝
的请求等。
回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执⾏回退逻辑。回退逻辑由开发⼈员⾃⾏提供,例如返回⼀个缺省值。
自我修复:断路器打开⼀段时间后,会⾃动进⼊“半开”状态。

Hystrix熔断应用

  • 服务消费者⼯程中引⼊Hystrix依赖坐标(也可以添加在⽗⼯程中)
  • 改造服务消费者工程 m-service-autodeliver-8090
<!--熔断器Hystrix-->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 服务消费者⼯程的启动类中 添加熔断器开启注解@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscoveryClient //开启服务注册与发现
@EnableCircuitBreaker //熔断器开启注解
//@EnableHystrix  //开启EnableHystrix
//@SpringCloudApplication  综合性的注解  @SpringCloudApplication  = @SpringBootApplication + @EnableDiscoveryClient + @EnableCircuitBreaker
public class AutodeliverApplication8090 {
    public static void main(String[] args) {
        SpringApplication.run(AutodeliverApplication8090.class, args);
    }

    /**
     * 注⼊RestTemplate
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
  • 定义服务降级处理⽅法,并在业务⽅法上使⽤@HystrixCommand的fallbackMethod属性关联到
    服务降级处理⽅法
    修改com.w.edu.controller.AutodeliverController,添加熔断的方法
 /**
     * 模拟请求超时,调用Hystrix控制
     * @param userId
     * @return
     */
    //使用@HystrixCommand进行熔断控制
    @HystrixCommand(
            commandProperties = {
                    //没个属性都是一个HystrixProperty
                    //HystrixCommandProperties  ==> execution.isolation.thread.timeoutInMilliseconds
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" ,value = "2000")
            }
    )
    @GetMapping("/checkStateTimeout/{userId}")
    public Integer findResumeOpenStateTimeout(@PathVariable Long userId) {
        Integer forObject =
                restTemplate.getForObject("http://m-service-resume/resume/openstate/" + userId,
                        Integer.class);
        System.out.println("======>>>调⽤微服务,获取到⽤户" + userId + "的默认     简历当前状态为:" + forObject);
        return forObject;
    }
  • 服务提供者端 模拟请求超时(线程休眠3s),只修改8081实例,8080不修改,对
    ⽐观察
  • m-service-resume-8081
@RestController
@RequestMapping("/resume")
public class ResumeController {
    @Autowired
    private ResumeService resumeService;

    @Value("${server.port}")
    private Integer port;

    //"/resume/openstate/1545132"
    @GetMapping("/openstate/{userId}")
    public Integer findDefaultResumeState(@PathVariable Long userId) {
// 模拟请求超时,触发服务消费者端熔断降级
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        return  resumeService.findDefaultResumeByUserId(userId).getIsOpenResume();
        return port;
    }
}

验证

在这里插入图片描述

在这里插入图片描述

  • 可以在类上使⽤@DefaultProperties注解统⼀指定整个类中共⽤的降级(兜底)⽅法
    fallbackMethod = "frostFallback"
@HystrixCommand(
            commandProperties = {
                    //没个属性都是一个HystrixProperty
                    //HystrixCommandProperties  ==> execution.isolation.thread.timeoutInMilliseconds
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" ,value = "2000")
            },
            fallbackMethod = "frostFallback"
    )
    @GetMapping("/checkStateTimeoutFallback/{userId}")
    public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {}
 /**
     * 模拟请求超时,调用Hystrix控制,添加回退操作
     * @param userId
     * @return
     */
    //使用@HystrixCommand进行熔断控制
    @HystrixCommand(
            commandProperties = {
                    //没个属性都是一个HystrixProperty
                    //HystrixCommandProperties  ==> execution.isolation.thread.timeoutInMilliseconds
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds" ,value = "2000")
            },
            fallbackMethod = "frostFallback"
    )
    @GetMapping("/checkStateTimeoutFallback/{userId}")
    public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {
        Integer forObject =
                restTemplate.getForObject("http://m-service-resume/resume/openstate/" + userId,
                        Integer.class);
        System.out.println("======>>>调⽤微服务,获取到⽤户" + userId + "的默认     简历当前状态为:" + forObject);
        return forObject;
    }

    /**
     * 回退方法
     * @param userId
     * @return
     */
    public Integer frostFallback( Long userId) {

        return -1;
    }

验证

在这里插入图片描述

Hystrix舱壁模式(线程池隔离策略)

所有熔断⽅法使⽤⼀个Hystrix线程池(10个线程),那么这样的话会导致问题,这个问题并不是扇出链路微服务不可⽤导致的,⽽是我们的线程机制导致的,如果⽅法A的请求把10个线程都⽤了,⽅法2请求处理的时候压根都没法去访问B,因为没有线程可⽤,并不是B服务不可⽤。
在这里插入图片描述

舱壁模式

为了避免问题服务请求过多导致正常服务⽆法访问,Hystrix 不是采⽤增加线程数,⽽是单独的为每⼀个控制⽅法创建⼀个线程池的⽅式,这种模式叫做“舱壁模式",也是线程隔离的⼿段
在这里插入图片描述

应用

  • 应用之前查看线程情况
    查看线程情况
  • 添加线程池隔离策略
 threadPoolKey = "findResumeOpenStateTimeoutFallback",
  threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "2"),
                    @HystrixProperty(name = "maxQueueSize", value = "20")
       
 //使用@HystrixCommand进行熔断控制
    @HystrixCommand(
            threadPoolKey = "findResumeOpenStateTimeoutFallback",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "2"),
                    @HystrixProperty(name = "maxQueueSize", value = "20")
            },
            commandProperties = {
                    //没个属性都是一个HystrixProperty
                    //HystrixCommandProperties  ==> execution.isolation.thread.timeoutInMilliseconds
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
            },
            fallbackMethod = "frostFallback"

    )
    @GetMapping("/checkStateTimeoutFallback/{userId}")
    public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {
        Integer forObject =
                restTemplate.getForObject("http://m-service-resume/resume/openstate/" + userId,
                        Integer.class);
        System.out.println("======>>>调⽤微服务,获取到⽤户" + userId + "的默认     简历当前状态为:" + forObject);
        return forObject;
    }
  • 查看线程情况
    在这里插入图片描述

Hystrix工作流程和高级应用

在这里插入图片描述
1)当调⽤出现问题时,开启⼀个时间窗(10s)
2)在这个时间窗内,统计调⽤次数是否达到最⼩请求数?
如果没有达到,则重置统计信息,回到第1步
如果达到了,则统计失败的请求数占所有请求数的百分⽐,是否达到阈值?
如果达到,则跳闸(不再请求对应服务)
如果没有达到,则重置统计信息,回到第1步
3)如果跳闸,则会开启⼀个活动窗⼝(默认5s),每隔5s,Hystrix会让⼀个请求通过,到达那个问题服务,看 是否调⽤成功,如果成功,重置断路器回到第1步,如果失败,回到第3步

 //使用@HystrixCommand进行熔断控制
    @HystrixCommand(
            threadPoolKey = "findResumeOpenStateTimeoutFallback",
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "2"),
                    @HystrixProperty(name = "maxQueueSize", value = "20")
            },
            commandProperties = {
                    //没个属性都是一个HystrixProperty
                    //HystrixCommandProperties  ==> execution.isolation.thread.timeoutInMilliseconds
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000"),
                    @HystrixProperty(name =
                            "metrics.rollingStats.timeInMilliseconds", value = "8000"),
                    @HystrixProperty(name =
                            "circuitBreaker.requestVolumeThreshold", value = "2"),
                    @HystrixProperty(name =
                            "circuitBreaker.errorThresholdPercentage", value = "50"),
                    @HystrixProperty(name =
                            "circuitBreaker.sleepWindowInMilliseconds", value = "3000")
            },
            fallbackMethod = "frostFallback"

    )
    @GetMapping("/checkStateTimeoutFallback/{userId}")
    public Integer findResumeOpenStateTimeoutFallback(@PathVariable Long userId) {}
  • 或者通过配置文件配置(消费者端)
# 配置熔断策略:
hystrix:
  command:
    default:
      circuitBreaker:
        # 强制打开熔断器,如果该属性设置为true,强制断路器进⼊打开状态,将会拒绝所有的请求。 默认false关闭的
        forceOpen: false
        # 触发熔断错误⽐例阈值,默认值50%
        errorThresholdPercentage: 50
        # 熔断后休眠时⻓,默认值5秒
        sleepWindowInMilliseconds: 3000
        # 熔断触发最⼩请求次数,默认值是20
        requestVolumeThreshold: 2
      execution:
        isolation:
         thread:
           #熔断超时设置,默认为1秒
           timeoutInMilliseconds: 2000
  • 基于springboot的健康检查观察跳闸状态,
    父工程添加依赖
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# springboot中暴露健康检查等断点接⼝
management:
  endpoints:
    web:
      exposure:
        include: "*"
  # 暴露健康接⼝的细节
  endpoint:
    health:
      show-details: always
  • 访问健康检查接⼝:http://localhost:8090/actuator/health
    通过PostMan 循环访问消费者接口,可观察到hystrix的工作状态
    在这里插入图片描述
    在这里插入图片描述 - hystrix正常⼯作状态在这里插入图片描述

  • 跳闸状态
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刚仔灬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值