SpringCloud 断路器 - Hystrix(服务降级,服务熔断)

官网停更说明

官网:https://github.com/Netflix/Hystrix

Hystrix目前已经停更进入维护阶段:(代替品:Spring cloud Alibaba Sentinel)
不过Hystrix的设计和思想理念非常好,任然值得一探究竟

在这里插入图片描述

基本介绍

分布式系统所面临的问题

服务雪崩
在这里插入图片描述

Hystrix是什么

在这里插入图片描述

Hystrix几个概念介绍

  • 服务降级
    服务提供者的服务器忙,不让客户端等待,并立刻返回一个友好提示,fallback

    发生服务降级的几种情况:

    1. 程序运行异常
    2. 超时
    3. 服务熔断触发服务降级
    4. 线程池/信号量打满也会导致服务降级
  • 服务熔断
    类比保险丝,达到最大的访问量后,直接拒绝访问,拉闸限电,然后调用服务降级的方法返回友好提示

    服务降级->进而熔断 ->恢复调用链路 (具有恢复功能)

  • 服务限流

    秒杀高并发等操作,严禁一窝蜂过来拥挤,大家排队,一秒N个,有序进行

Hystrix服务降级

服务降级主要解决的问题:
超时导致服务器变慢,----------> 超时不在等待
出错(宕机或者程序运行出错)-------> 返回友好提示

  • 服务提供者超时了,服务调用者不能一直卡死等待,必须有服务降级
  • 服务提供者者宕机了,服务调用者不能一直等待卡死,必须有服务降级
  • 服务提供者OK,调用者自己出故障或者有自我要求(自己等待时间小于服务提供者处理的时间),自己降级处理

Hystrix服务降级配置

服务降级配置一般配置在服务的调用者,当然服务的提供者者也可以配置,具体看业务场景

先添加依赖:

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

主启动类激活注解@EnableCircuitBreaker

@EnableCircuitBreaker
@SpringBootApplication
public class SpringcloudProviderPaymentApplication {

需要服务降级的方法使用注解@HystrixCommand

场景使用:
当一个方法调用设置方法调用超时的时间,设定时间内可以正常运行,调用超过了方法设定的超时时间,则需要有一个兜底方法处理,作为服务降级的fallback(作为备选的响应方法)

@HystrixCommand注解参数解释看注释

	// fallbackMethod 兜底方法,降级方法,备用方法
 	@HystrixCommand(fallbackMethod = "paymentTimeout",commandProperties = {
            // 该注解表示对应线程设定的超时时间限制,超过该时间,就调用fallback 降级方法
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000")
    })
    @GetMapping("/payment/timeout/get/{id}")
    public CommonResult<Payment> getPaymenttimeoutById(@PathVariable("id") Long id) {
        // 模拟业务逻辑处理的时间
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Payment payment = paymentService.getPaymentById(id);
        return new CommonResult<Payment>(200, port, payment);
    }

    // 兜底方法,fallback
    public CommonResult<Payment> paymentTimeout(Long id) {
        
        return new CommonResult<Payment>(401, "方法调用超时或者出错 ", null);
    }

一旦调用服务方法出错抛出异常信息后或者超时,会自动调用@HystrixCommand标注好的fallbackMethod调用类中指定的方法

运行结果:
在这里插入图片描述

我们修改下上面的代码,让程序运行不是超时而是运行报错,程序也会自动调用@HystrixCommand标注好的fallbackMethod调用类中指定的方法

  @HystrixCommand(fallbackMethod = "paymentTimeout",commandProperties = {
            // 该注解表示对应线程设定的超时时间限制,超过该时间,就调用fallback 降级方法
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000")
    })
    @GetMapping("/payment/timeout/get/{id}")
    public CommonResult<Payment> getPaymenttimeoutById(@PathVariable("id") Long id) {
    	// 运行报错
        int i = 10/0;
        Payment payment = paymentService.getPaymentById(id);
        return new CommonResult<Payment>(200, port, payment);
    }

运行结果:
在这里插入图片描述

Hystrix全局服务降级配置

注解:@DefaultProperties(defaultFallback = "")
在这里插入图片描述

添加到类上,如果方法上的@HystrixCommand没有明确指定fallbackMethod,那么默认就会使用
@DefaultProperties(defaultFallback = "") 指定的fallback

代码示例:

@DefaultProperties(defaultFallback = "globalFallback")
@RestController
public class PaymentController {


    // 兜底方法,fallback
    public CommonResult<Payment> globalFallback() {
        return new CommonResult<Payment>(401, "globalFallback方法调用超时或者出错 ", null);
    }

    @HystrixCommand
    @GetMapping("/payment/timeout/get/{id}")
    public CommonResult<Payment> getPaymenttimeoutById(@PathVariable("id") Long id) {
        int i = 10/0;
        Payment payment = paymentService.getPaymentById(id);
        return new CommonResult<Payment>(200, port, payment);
    }

运行结果:
在这里插入图片描述

Hystrix服务降级配置优化

Hystrix服务降级配置一般情况下都是配置在服务的调用者这边。

  1. 上述的2种配置都有个问题,服务降级配置和业务逻辑代码混合一起,配置混乱,

  2. 一般情况下,微服务中,服务的调用者去调用服务的提供者,我们服务降级配置往往只关心 具体服务调用者调用服务的提供者的那些方法。

  3. 在服务调用者中我们一般可以用Feign客户端调用服务提供者,此时我们只需要为Feign客户端定义的接口 添加一个服务降级处理的实现类即可实现解耦

在服务调用的过程中,我们一般会遇到异常时以下几种:

  • 运行时异常
  • 服务调用超时
  • 服务宕机

优化配置方式:

服务的调用者一般会有Feign客户端定义的接口(文章参考服务调用OpenFeign
代码如下:

Feign客户端定义的接口:
注意@FeignClient注解上的参数意义

@Component
// 参数1:要调用的微服务名, 参数2:服务降级处理类
@FeignClient(value = "SPRINGCLOUD-PAYMENT-PROVIDER", fallback = OpenFeignPaymentFallBackService.class) 
public interface OpenFeignPaymentServer {

    @GetMapping("/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

    @GetMapping("/payment/timeout/get/{id}")
    public CommonResult<Payment> getPaymenttimeoutById(@PathVariable("id") Long id);
}

新建一个类实现Feign客户端定义的接口统一为接口里面的方法进行异常处理

@Component
public class OpenFeignPaymentFallBackService implements OpenFeignPaymentServer {
    @Override
    public CommonResult<Payment> getPaymentById(Long id) {
        return new CommonResult<Payment>(401, "getPaymentById方法调用超时或者出错 ", null);
    }

    @Override
    public CommonResult<Payment> getPaymenttimeoutById(Long id) {
        return new CommonResult<Payment>(401, "方getPaymenttimeoutById法调用超时或者出错 ", null);
    }
}

配置文件YML添加配置:

# 用于服务降级,在注解@FeignClient中添加fallback属性值
feign:
  hystrix:
    enabled: true  # 在Feign中开启Hystrix

有了以上的配置,就不需要再其他任何方法和类上添加关于Hystrix服务降级的任何注解和信息

运行结果:
配置已经生效,当调用服务SPRINGCLOUD-PAYMENT-PROVIDER的方式的时候,如果出现调用异常,那么服务调用者就会调用最后的fallback方法作为作为响应,
在这里插入图片描述

Hystrix服务降级总结

在服务调用端有了以上配置(Hystrix服务降级配置优化),就算服务提供者宕机,或者出现各种异常,但是我们做了服务降级处理,让客户端在服务端不可用的时候也会获得提示信息,而不是挂起耗死服务器

Hystrix服务熔断

服务熔断机制是应对雪崩效应的一种服务链路保护机制。当扇出链路的某个微服务出错不可用或者响应世间太长时,会进行服务降级,进而熔断该节点微服务的调用,快速返回错误响应信息 。

当检测到该节点微服务调用响应正常后,恢复调用链路

在Spring Cloud框架里面,熔断机制通过Hystrix实现。Hystrix会监控微服务间的调用状况,当失败的调用到一定阀值时,默认是5秒20次调用失败,就会启动熔断机制

在这里插入图片描述

Hystrix服务熔断配置

下面注解@HystrixProperty 各个参数的说意思:
参数意思是在10秒内请求次数超过10,并且调用错误率达到 60% ,那么该接口就进行熔断,此时就算传入正确的参数,也进行服务降级,待一定时间后,如果会进行一个请求测试,如果可以正常访问,那么熔断器会自动关闭

 //=====服务熔断
    @HystrixCommand(fallbackMethod = "globalFallback", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少后跳闸
    })
    @GetMapping("/payment/timeout/get/{id}")
    public CommonResult<Payment> getPaymenttimeoutById(@PathVariable("id") Long id) {
        if (id < 0) {
            throw new RuntimeException("id不能为负数");
        }
        Payment payment = paymentService.getPaymentById(id);
        return new CommonResult<Payment>(200, port, payment);
    }

调用结果,当我们输入正数调用的时候,返回正常,
参数传入负数的时候,如果在10秒内,请求次数超过10次,此时错误率已经超过60%,那么服务就会进行熔断,进而服务降级。

Hystrix服务熔断总结

熔断类型:

在这里插入图片描述
断路器在什么情况下开始起作用:
在这里插入图片描述

断路器开启或者关闭的条件:
在这里插入图片描述

断路器打开之后:
在这里插入图片描述

Hystrix工作流程图及步骤

工作流程图:
在这里插入图片描述

步骤说明:
在这里插入图片描述

HystrixDashboard图形界面

在这里插入图片描述

HystrixDashboard图形界面搭建步骤:

  1. 新建一个springboot工程

  2. 添加依赖 pom依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  3. 主启动类添加注解

    @EnableHystrixDashboard
    @SpringBootApplication
    public class SpringcloudHystrixdashboardApplication {
    
  4. 修改端口号

    server:
      port: 9001
    
  5. 所有Provider微服务提供服务,都需要添加以下依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  6. 启动监控服务

访问地址:http://localhost:9001/hystrix

在这里插入图片描述

注意新版本的Hystrix需要在主启动类(被监控的服务的主启动类)上指定路径,如下代码示例:

@EnableDiscoveryClient
@EnableCircuitBreaker
@SpringBootApplication
public class SpringcloudProviderPaymentApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudProviderPaymentApplication.class, args);
    }

    /**
     *此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
     *ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
     *只要在自己的项目里配置上下面的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

现在我们用 9001 监控 我们需要监控的服务提供者,

在9001 上添加 需要监控的服务的地址,如下图所示

被监控的服务地址:http://localhost:8003/hystrix.stream
在这里插入图片描述

监控如下所示:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值