服务降级——Hystrix熔断器

一、介绍

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

在这里插入图片描述

什么是Hystrix

Hystrix是一个用于处理分布式系统的延迟容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix通过隔离对远程系统,服务和第三方库的访问点,避免级联故障,以提高分布式系统的弹性

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似于物理的熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

Hystrix已进入维护阶段。主要有服务降级、服务熔断、接近实时的监控、限流、隔离等等,其官方文档参考。当然Hystrix现在已经停更了,虽然有一些替代品,但是学习Hystrix及其里面的思想还是非常重要的!

二、Hystrix重要概念

1. 服务降级——Fall Back

服务端忙或不可用时,不会让客户端等待,会立刻返回一个友好提示。比如像客户端提示服务器忙,请稍后再试等。

哪些情况会触发服务降级?如程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级。

2. 服务熔断——Break

服务熔断就相当于物理上的熔断保险丝。当服务端达到最大服务访问后,直接拒绝访问,然后调用服务降级的方法并返回友好提示。

3. 服务限流——Flow Limit

对于秒杀活动等高并发的操作,严禁一窝蜂的过来拥挤,而是采取有序进行。

三、服务降级Fall Back

当服务不可用或超时时,导致页面不能及时相应,此时我们可以使用服务降级来应对这种情况

在这里插入图片描述

1、在服务提供方配置服务降级

1、构建项目,并在服务提供方pom添加依赖
<!--hystrix-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、主启动类

添加 @EnableCircuitBreaker 注解对熔断器进行激活

/**
 * @author junfeng.lin
 * @date 2021/2/20 18:08
 */
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixServer8005 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixServer8005.class,args);
    }
}
3、在对应的方法上实现服务降级

在服务提供方的业务类上启用 @HystrixCommand 实现报异常后如何处理,也就是一旦调用服务方法失败并抛出了错误信息后,会自动调用 @HystrixCommand 标注好的fallbackMethod服务降级方法。

2、在服务消费方配置服务降级

1、pom

跨服务访问,需要添加feign依赖;使用eureka注册中心,需要添加eureka客户端依赖;使用hystrix,添加hystrix依赖

<!--openfeign-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--eureka client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--hystrix-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、修改.yaml配置文件,使之支持hystrix
feign:
  hystrix:
    enabled: true
3、在主启动类上激活Hystrix服务
@EnableHystrix
4、在对应的方法上实现服务降级

由于消费方访问服务提供方的时间超过了1.5秒,那么就会访问自己的降级服务方法timeOutHandler

@GetMapping("/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "timeOutHandler", commandProperties = {
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
public String paymentInfo_TimeOut(@PathVariable("id") Long id) {
    return myFeign.paymentInfo_TimeOut(id);
}

	/**
     * 处理方法
     * @param id
     * @return
     */
public String timeOutHandler(Long id) {
    return "系统忙,请稍后再试。。。";
}

在这里插入图片描述

存在问题:

在每个方法上实现服务降级导致了两个问题:

1、每个业务方法都对应了一个服务降级犯法,导致代码膨胀

可以通过在全局配置降级方法,将统一的和独特的降级方法分隔开,合理减少了代码量,在Controller上配置@DefaultProperties(defaultFallback = "global_FallbackMethod"),在要处理服务降级的方法上配置@HystrixCommand

无论是否配置了定制服务降级方法,都要在其服务上加入注解 @HystrixCommand, 否则服务降级和该服务没关系

修改如下:

/**
 * @author junfeng.lin
 * @date 2021/2/18 2:01
 */
@RestController
@DefaultProperties(defaultFallback = "global_FallbackMethod") //全局服务降级
public class HystrixConsumeController {
    @Autowired
    private MyFeign myFeign;

    @GetMapping("/getPort")
    public String getPort() {
        return myFeign.getPort();
    }

    @GetMapping("/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Long id) {
        return myFeign.paymentInfo_OK(id);
    }

    /**
     * 模拟代码错误
     * @param id
     * @return
     */
    @GetMapping("/hystrix/cal_error/{id}")
    @HystrixCommand
    public String cal_error(@PathVariable("id") Long id) {
        int i = 1/0;
        return String.valueOf(i);
    }

    /**
     * 模拟运行时超时
     * @param id
     * @return
     */
    @GetMapping("/hystrix/timeout/{id}")
    @HystrixCommand(fallbackMethod = "timeOutHandler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
    })
    public String paymentInfo_TimeOut(@PathVariable("id") Long id) {
        return myFeign.paymentInfo_TimeOut(id);
    }

    /**
     * 处理方法
     * @param id
     * @return
     */
    public String timeOutHandler(Long id) {
        return "系统忙,请稍后再试。。。";
    }
    /**
     * 全局服务降级方法
     * @return
     */
    public String global_FallbackMethod() {
        return "全局异常处理信息";
    }
}
2、服务降级方法和业务逻辑混合在了一起,这会导致代码混乱,业务逻辑不清晰。

可以通过为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。而在Controller中去掉一切处理服务降级的配置,即可实现

package jun.Feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.concurrent.TimeUnit;

/**
 * @author junfeng.lin
 * @date 2021/2/18 2:05
 */
@Component
@FeignClient(value = "eureka-order", fallback = MyFeignFallback.class)
public interface MyFeign {
    @GetMapping("/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Long id);
}
package jun.Feign;

import org.springframework.stereotype.Component;

/**
 * @author junfeng.lin
 * @date 2021/2/21 1:43
 */
@Component
public class MyFeignFallback implements MyFeign{
    @Override
    public String paymentInfo_TimeOut(Long id) {
        return "paymentInfo_TimeOut异常处理。。。";
    }
}

/**
     * 模拟运行时超时
     * @param id
     * @return
     */
    @GetMapping("/hystrix/timeout/{id}")
//    @HystrixCommand(fallbackMethod = "timeOutHandler", commandProperties = {
//            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
//    })
    public String paymentInfo_TimeOut(@PathVariable("id") Long id) {
        return myFeign.paymentInfo_TimeOut(id);
    }

在这里插入图片描述

四、服务熔断 Break

1、熔断机制概述

熔断机制是应对雪崩效应的一种微服务链路保护机制,服务熔断会导致服务降级,当检测到该节点微服务调用响应正常后,恢复调用链路。也就是说,服务熔断在服务好了之后会重新允许访问服务。

在SpringCloud框架中,熔断机制通过Hystrix实现。Hystrix会监控微服务间的调用状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是 @HystrixCommand

2、服务提供方

在服务提供方配置如下:

@Override
/**
 * 服务熔断
 * fallbackMethod                               服务降级方法
 * circuitBreaker.enabled                       是否开启断路器
 * circuitBreaker.requestVolumeThreshold        请求次数
 * circuitBreaker.sleepWindowInMilliseconds     时间窗口期
 * circuitBreaker.errorThresholdPercentage      失败率达到多少后跳闸
 * 以下配置意思是在10秒时间内请求5次,如果有6此是失败的,就触发熔断器
 * 注解@HystrixProperty中的属性在com.netflix.hystrix.HystrixCommandProperties类中查看
 * @param id
 * @return
 */
@HystrixCommand(fallbackMethod = "errorHandler", commandProperties = {
        @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})
public String testBreak(Long id) throws Exception {
    if (id < 0) {
        throw new Exception("id不能小于0");
    }
    return "线程池: " + Thread.currentThread().getName() + " , id: " + id;
}

/**
 * 处理方法
 * @param id
 * @return
 */
public String errorHandler(Long id) {
    return "系统忙,请稍后再试";
}

上述的逻辑是,当10秒内有6次(60%的次数)请求超时或异常时,会触发服务熔断,此时不会调用主逻辑,而是直接调用服务降级的方法,过一段时间后,当检测到服务可用时,会重新开启服务。

当熔断器打开后,对主逻辑进行熔断之后,Hystrix会启动一个 休眠时间窗 , 在这个时间窗内,降级逻辑是临时的主逻辑,当休眠时间窗到期,熔断器会进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求能够正常访问,则熔断器会进入闭合状态,从而恢复主逻辑,如果注册请求依然有问题,则熔断器继续保持打开状态,并且休眠时间窗重新计时。

3、熔断器状态
熔断器打开OPEN请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态(HALF-OPEN)。
熔断器关闭CLOSED熔断关闭不会对服务进行熔断,服务可用
熔断器半开HALF-OPEN部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断;否则继续处于熔断状态,并重新计时

在这里插入图片描述

4、熔断器工作原理
官网:https://github.com/Netflix/Hystrix/wiki/How-it-Works

五、服务监控Hystrix Dashboard

Hystrix提供了准实时的调用监控——Hystrix Dashboard,Hystrix会持续的记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等。SpringCloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。

1、新建Module
  • pom依赖
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
  • 指定端口号
server:
  port: 9001
  • 主启动类上添加@EnableHystrixDashboard注解开启Hystrix Dashboard功能
package org.jun;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

/**
 * @author junfeng.lin
 * @date 2021/2/21 13:58
 */
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class,args);
    }
}
  • 访问http://localhost:9001/hystrix

在这里插入图片描述

2、要监控的服务提供方
  • 添加监控依赖
<!--actuator监控信息完善-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 配置类

为了让服务提供方的服务能被Hystrix Dashboard监控到,需要在提供方服务的主启动类中添加如下配置

/**
     *此配置是为了服务监控而配置
     *ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream"
     */
    @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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值