【分布式】SpringCloud(6)--Hystrix服务熔断与降级

1.Hystrix概述

1.1.什么是Hystrix

Hystrix是一个用于处理分布式系统的延迟和容错的开源库。Hystrix主要用于处理分布式系统中复杂多变的服务依赖调用失败、超时、异常等状况,保证一个服务依赖出问题的状况下,提供一个服务预期的、可处理的备选响应(FallBack),避免微服务总体级联故障,以提升分布式系统的弹性。git

 

1.2.Hystrix的做用是什么

Hystrix旨在执行如下操做:github

  • 提供保护并控制延迟和失败,以及经过第三方客户端库(一般是经过网络)访问依赖项致使的失败。
  • 切断复杂的分布式系统中的级联故障。
  • 快速响应并快速恢复。
  • 回退并在可能的状况下正常降级。
  • 启用近乎实时的监视,警报和操控。

 

1.3.Hystrix能解决什么问题

Hystrix在分布式项目中主要用于处理:spring

  • 服务降级
  • 服务熔断
  • 服务限流
  • 接近实时地监控

 

2.Hystrix服务熔断

2.1.服务熔断机制

首先对应服务熔断咱们要理解“服务雪崩”的概念,服务雪崩是多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。若是扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用愈来愈多的系统资源,进而引发系统崩溃,就是所谓的“雪崩”。数据库

熔断机制是应对雪崩效应的一种微服务链路保护机制api

当扇出链路的某个微服务不可用或者响应时间太长时,就会经过熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。网络

 

2.2.简单实现一个Hystrix熔断

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

这里咱们仍是基于咱们以前博客的微服务项目springcloud-provider-dept-8001 服务端 复制一份做为hystrix的微服务项目。app

①添加hystrix pom.xml依赖包:框架

<!--引入hystrix-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

 

②修改application.yml配置,修改了实例名称:分布式

server:
  port: 8001
##省略了数据库链接信息与mybatis配置

#eureka的配置,肯定客户端服务注册到eureka服务列表内
eureka:
  client:
    service-url:
      #集群配置
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
      #defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept-hystrix-8001  #修改eureka上默认的服务描述信息
    prefer-ip-address: true  #访问路径能够显示ip地址

 

③基于Controller层的调用方法经过id获取Dept用户来作异常断定:

@RestController
@RequestMapping("/dept")
public class DeptController {
    @Autowired
    private DeptService service;

    @GetMapping("/queryById/{id}")
    /*@HystrixCommand表示一旦调用服务方法失败并抛出了异常信息以后,
    会自动调用@HystrixCommand标注好的fallbackMethod中指定名称的方法*/
    @HystrixCommand(fallbackMethod = "processHystrixGet")
    public Dept queryById(@PathVariable("id") Long id){
        Dept dept = service.queryById(id);  //模拟当查询不到id或者id信息异常时返回错误异常的提示
        if(null == dept){
            throw new RuntimeException("id=>" + id + "不存在该用户,或者用户信息没法找到!");
        }
        return dept;
    };

    //熔断备选方法:异常回调信息显示
    public Dept processHystrixGet(@PathVariable("id") Long id){
        return new Dept()
                .setDeptno(id)
                .setDname("id=>" + id + "没有对应的信息,null--@Hystrix")
                .setDbSource("no this database in MySQL");
    }
}

 

④在主启动类上添加对hystrix的熔断机制的支持:

@SpringBootApplication
@EnableEurekaClient  //在服务启动后自动注册到eureka中
@EnableDiscoveryClient  //服务发现
@EnableCircuitBreaker  //启用对hystrix的熔断机制的支持
public class DeptProvider8001_Hystrix_App {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
    }
}

 

⑤启动Eureka客户端、Hystrix服务端进行访问验证:

访问正常存在的服务id,能返回正常数据:

 

访问异常不存在的id时,返回fallback方法中的信息:

 

 能够看出,当执行调用某个微服务发生异常时,Hystrix能经过自定义的fallbackMethod作异常的错误返回,快速进行异常熔断机制。

服务熔断是在服务运行的状况下,对于服务内部执行错误的异常状况的一种处理方式。

 

3.Hystrix服务降级

3.1.服务降级机制

服务降级是从网站总体的负载考虑,当某个服务在某一时间内承受大量的服务请求,而须要极大的资源消耗,须要关闭当前系统的某些服务,作资源的扩充。牺牲单个服务的运行,当再次访问这单个服务的时候,经过服务降级处理,返回给客户设定的默认缺省值

至关于弃军保帅,维护的是整个系统的可用性。

 

3.2.简单实现服务降级

服务降级这里从客户端进行实现。

(1)首先在springcloud-api中定义一个降级以后的回调函数类,实现FalllbackFactory接口,接口中实现了对应请求信息的异常处理方法:

@Component  //注意不要忘记添加,须要把类加载进Spring容器中才能获取到
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public boolean addDept(Dept dept) {
                return false;
            }

            @Override
            public Dept queryById(Long id) {
                return new Dept().setDeptno(id).setDname("该ID:" + id + "没有对应的信息,Consumer客户端提供的降级信息,此刻服务provider已经关闭").
                        setDbSource("no this database in MySQL");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }
        };
    }
}

 

(2)对应api接口中使用fallabckFatory去指定调用的是哪一个class实现类:

//value中对应服务提供方的名字
//服务降级:表示DeptClientService当前接口中任何一个方法出了问题:都去找DeptClientServiceFallbackFactory回调处理
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class)
@Component //注入到容器中
public interface DeptClientService {
    /**
     * 接口中的三个方法对应服务提供者的三个方法
     * 这里面的接口对应服务提供者的controller接口,名称必须一致,而后接口的Mapping映射url必须一致
     * @param dept
     * @return
     */

    @PostMapping("/dept/add")
    public boolean addDept(Dept dept);

    @GetMapping("/dept/queryById/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/queryAll")
    public List<Dept> queryAll();
}

 

(3)基于FeignClinet调用,则须要修改服务提供者中application.yml,开启feign中对hystrix的支持:

#开启降级feign.hystrix支持
feign:
  hystrix:
    enabled: true

 

(4)测试验证:

步骤:启动三个Eureka注册中心700一、700二、7003,启动provider-dept-8001做为服务提供者、启动consumer-dept-feign服务消费者:

能够看到服务提供者已经注册进去并正常运行:

 

 

经过客户端consumer-feign的81端口也能访问到对应的id数据:

 

(5)模拟服务熔断异常:

关闭服务提供方provider-dept-8001,同时访问81端口的数据请求:

 

 能够看到此时调用到了咱们编写的fallbackFactory中的回调方法显示降级信息。

因此即便服务关闭以后,Hystrix的服务熔断机制也能避免大量重复无效访问带来的服务异常,能较好的提供客户体验。

 

本节涉及实例及相关代码已上传至github:

https://github.com/devyf/SpringCloud_Study/tree/main/springcloud_hello