SpringCloud-Hystrix服务熔断-04

Hystrix服务熔断

分布式面临的四大问题

复杂的分布式体系结构中的应用程序有数十个的依赖关系,每个依赖关系在某些时候可能会调用失败

1. 服务雪崩

多个微服务调用的时候,例如A调用B,B再调用C,C在调用其他的,这就是所谓的"扇出",如果扇出的链路上出现了某个服务响应的时间过长或者不可用,对于A的调用就会占用越来越多的资源,从而引起系统的崩溃,这就是所谓的"雪崩效应"
image
对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源在几秒内饱和,还可能导致服务之间的延迟增加,备份队列,线程和其他资源紧张,导致整个系统发生更多的联级故障,这些都表示需要对故障和延迟进行隔离和管理,达到单个依赖关系的失败而不影响整个应用程序或者系统运行

2.什么是Hystrix

  1. 是一个应用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的调用失败,超时,异常等等,他能保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免了联级故障,提高了分布式系统的弹性
  2. 断路器,是一种开关装置,当服单元发生故障之后,通过断路器的故障监控(类似于保险丝)向调用方返回一个服务预期的,可处理的备选响应(fallback),而不是长时间的等待或者抛出异常,这样就可以保证服务调用方的线程不会被长时间,不必要的占用,从而避免了雪崩
    image

3. Hystrix能干什么

  • 服务降级
  • 服务熔断
  • 服务限流
  • 实时监控(豪猪)
    一切正常时
    image
    有阻塞之后
    image
    从而导致
    image
    使用了之后
    image

4. 什么是服务熔断

  • 是对应雪崩效应的一种微服务链路保护机制
  • 当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阀值缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是:@HystrixCommand。
    服务熔断机制解决的问题
  1. 依赖的对象不稳定时,能快速失败
  2. 快速失败后,能根据一定的算法动态试探所依赖的对象能否恢复

5. 案例

  1. 新建springcloud-provider-dept-sli-8001将原来的8001的pom.xml和resource还有java代码复制到这个项目中
<!--导入Hystrix依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sli</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
  1. 调整yaml的配置文件
server:
  port: 8001
# mybatis配置
mybatis:
  # springcloud-api 模块下的pojo包
  type-aliases-package: com.haust.springcloud.pojo
  # 本模块下的mybatis-config.xml核心配置文件类路径
  config-location: classpath:mybatis/mybatis-config.xml
  # 本模块下的mapper配置文件类路径
  mapper-locations: classpath:mybatis/mapper/*.xml
# spring配置
spring:
  application:
    #项目名
    name: springcloud-provider-dept
  datasource:
    # 德鲁伊数据源
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8
    username: root
    password: root
# Eureka配置:配置服务注册中心地址
eureka:
  client:
    service-url:
      # 注册中心地址7001-7003
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provider-dept-sli-8001 #修改Eureka上的默认描述信息
    prefer-ip-address: true #改为true后默认显示的是ip地址而不再是localhost
#info配置
info:
  app.name: haust-springcloud #项目的名称
  company.name: com.haust #公司的名称
  1. 修改controller
@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;
//根据id查询部门信息,如果信息出现错误的话,则走hystrixGet这段备选代码
    @HystrixCommand(fallbackMethod = "hystrixGet")
    @RequestMapping("/dept/get/{id}")//根据id查询
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if (dept==null){
            throw new RuntimeException("这个id=>"+id+",不存在该用户,或信息无法找到~");
        }
        return dept;
    }
//根据id查询备选方案(熔断)
    public Dept hystrixGet(@PathVariable("id") Long id){
        return new Dept().setDeptno(id)
                .setDname("这个id=>"+id+",没有对应的信息,null---@Hystrix~")
                .setDb_source("在MySQL中没有这个数据库");
    }
}
  1. 为主启动类中添加熔断的支持注解@EnablecCircuitBreaker
@SpringBootApplication
@EnableEurekaClient // EnableEurekaClient 客户端的启动类,在服务启动后自动向注册中心注册服务
@EnableDiscoveryClient
@EnableCircuitBreaker // 添加对熔断的支持注解
public class HystrixDeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDeptProvider_8001.class,args);
    }
}

6. 服务降级

  1. 什么是服务降级:是指在服务器压力增加的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。就是尽可能的把系统资源让给优先级高的服务。
  2. 例如当一定的时间内A的访问量暴增,B和C的访问量较少,为了缓解A的压力,需要将B,C暂时关闭一些服务功能,分担A的压力,叫服务降级

案例介绍

  1. 在springcloud-api的模块下面的service包中新建降级配置类DeptClientServiceFallBackFactory.java
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {
    @Override
    public DeptClientService create(Throwable cause) {
        return new DeptClientService() {
            @Override
            public Dept queryById(Long id) {
                return new Dept()
                        .setDeptno(id)
                        .setDname("id=>" + id + "没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭")
                        .setDb_source("没有数据~");
            }
            @Override
            public List<Dept> queryAll() {
                return null;
            }
            @Override
            public Boolean addDept(Dept dept) {
                return false;
            }
        };
    }
}
  1. 在DeptClientService中指定降级的配置类DeptClientServiceFallBackFactory
@Component //注册到spring容器中
//@FeignClient:微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallBackFactory.class)//fallbackFactory指定降级配置类
public interface DeptClientService {
    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);
    @GetMapping("/dept/list")
    public List<Dept> queryAll();
    @GetMapping("/dept/add")
    public Boolean addDept(Dept dept);
}
  1. 在springcloud-consumer-dept-feign中模块开启降级
# 开启降级feign.hystrix
feign:
  hystrix:
    enabled: true
  1. 测试

7. 降级和熔断的区别

  • 服务熔断—>服务端:某个服务超时或异常,引起熔断~,类似于保险丝(自我熔断)
  • 服务降级—>客户端:从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时在客户端,我们可以准备一个 FallBackFactory ,返回一个默认的值(缺省值)。会导致整体的服务下降,但是好歹能用,比直接挂掉强。
  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)
  • 实现方式不太一样,服务降级具有代码侵入性(由控制器完成/或自动降级),熔断一般称为自我熔断。

8. Dashboard流监控

  1. 新建模块springcloud-provider-dept-hystrix-8001添加依赖
<!--Hystrix依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--dashboard依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--Eureka-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
<!--实体类+web-->
<dependency>
    <groupId>com.haust</groupId>
    <artifactId>springcloud-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--热部署-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>
  1. 主启动类
@SpringBootApplication
// 开启Dashboard
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9001.class,args);
    }
}
  1. 给springcloud-provider-dept-hystrix-8001模块下面的主启动类添加如下的代码,添加监控
@SpringBootApplication
@EnableEurekaClient //EnableEurekaClient 客户端的启动类,在服务启动后自动向注册中心注册服务
public class DeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }
    //增加一个 Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //访问该页面就是监控页面
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
}
  1. 访问http://localhost:9001/hystrix
    image
  2. 进入监控页面
    image
    效果如下
    image
posted @ 2021-10-04 17:27  1_f  阅读(17)  评论(0)    收藏  举报