目录

  • 1.分布式系统面临的问题
  • 2.服务雪崩
  • 3.什么是Hystrix?
  • 4.Hystrix的作用
  • 5.服务熔断
  • 1.什么是服务熔断
  • 2.入门案例
  • 3.显式提供服务的服务器的IP
  • 4.小结



1.分布式系统面临的问题

  • 复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免失败!

2.服务雪崩

  • 多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长,或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”
  • 比如一台服务器上的众多微服务中有一个微服务叫A,如果A崩溃了,不能提供服务了,那么所有请求这个微服务的用户就会一直等待,等待地人越来越多,那么占用的服务器的系统资源就越多[因为服务器需要维持用户的请求队列,先进先出],最终将会导致资源被占完,这个服务器就会拒绝服务,那么这个服务器上的其他服务也就访问不了了,这就是雪崩效应
  • 对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统
  • 我们需要,弃车保帅
  • 最简单的做法就是做服务备份,注意:服务备份大多数情况下不是指将这个服务再拷贝一份,更多的时候是指当这个服务崩溃之后,系统自动切换服务备份顶上,服务备份一般不会提供服务,而是向客户端返回一些提示信息,提示当前的这个服务崩溃了,而不是让用户等待,一直占用服务器的资源;当然备份也可以是将当前这个服务拷贝一份,当这个服务奔溃的时候切换它继续提供正常的服务,但是这样成本就增加了,因为按照这种备份,原来的服务器资源需要翻倍

3.什么是Hystrix?

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

4.Hystrix的作用

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

当一切正常时,请求流可以如下所示:

Spring cloud gateway 熔断 降级_spring cloud


即以一个消费者的请求可能需要调用好几个微服务

当许多后端系统中有一个服务崩溃的时候,这个崩溃的微服务将会阻塞整个用户的请求,就比如下图中的微服务 I:

Spring cloud gateway 熔断 降级_服务熔断_02

即所有需要经过微服务I的消费者的请求都会卡在微服务I这里,服务器为了维持用户先后到达的顺序就会开启队列排队并维护一些其他的必要信息,但是随着请求微服务I的用户越来越多,阻塞越来越多,服务器被消耗的资源越来越多,最终就会导致服务器资源被耗尽,就会造成服务器上其他正常的服务都不能正常的被消费者请求,即造成了服务雪崩;如下图

Spring cloud gateway 熔断 降级_spring cloud_03


当使用hystrix包装每个基础依赖项时,上面的图表中所示的体系结构会发生类似于以下关系图的变化。即我们为每一个微服务都做一个服务备份,这个备份在微服务正常提供服务的情况下不会被调用,只有当微服务出现故障的时候才会被调用,代替原微服务继续为用户提供服务,而不是让用户一直阻塞在崩溃的微服务I这个地方,最终导致服务雪崩

Spring cloud gateway 熔断 降级_Hystrix_04


5.服务熔断

1.什么是服务熔断

  • 熔断机制是对应服务雪崩效应的一种微服务链路保护机制,比如上面说的加一个服务的备份
  • 在微服务架构中,微服务之间的数据交互通过远程调用完成,微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,此时如果链路上某个微服务的调用响应时间过长或者不可用,那么对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,导致“雪崩效应”。
  • 服务熔断是应对雪崩效应的一种微服务链路保护机制。例如在高压电路中,如果某个地方的电压过高,熔断器就会熔断,对电路进行保护。同样,在微服务架构中,熔断机制也是起着类似的作用。当调用链路的某个微服务不可用或者响应时间太长时,会进行服务熔断,不占用该节点微服务的调用,快速返回错误的响应信息;当检测到该节点微服务调用响应正常后,恢复调用链路。
  • 当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息,检测到该节点微服务调用响应正常后恢复调用链路在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阀值缺省是5秒内20次调用失败,就会启动熔断机制,我们在spring cloud中只需要使用一个熔断机制的注解是:@HystrixCommand 即可
  • 服务熔断解决如下问题:
  • 当所依赖的对象不稳定时,能够起到快速失败的目的
  • 快速失败后,能够根据一定的算法动态试探所依赖对象是否恢复

2.入门案例

  • 创建一个新的model,但是它是在原来的8001服务提供者模块的基础上进行的修改,即在原来没有加上熔断机制的8001上加上熔断机制,而SpringCloud框架里熔断机制通过Hystrix实现,所以我们需要导入Hystrix的依赖
  • 实现还是老4步
- 导入依赖
- 编写配置文件
- 开启这个功能:@EnableXXX
- 配置类
  • 创建子model:springcould-provider-dept-hystrix-8001
  • 拷贝8001里的所有东西
  • 导入Hystrix的依赖
<!--Hystrix依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <!--可见ribbon、Feign、Hystrix的依赖套路就是只修改最后的后缀即可-->
    <version>1.4.7.RELEASE</version>
</dependency>
  • 修改配置文件
  • 修改原来的controller,比如这里我们用按照id查询部门信息的方法举例子,我们让这个方法出错的时候就去调用我们备用的方法给前端返回信息(这就是使用hystrix实现的熔断机制,当原方法崩溃/报错不能正常提供服务的时候,直接切换备用的方法继续为客户端提供服务,而不是向客户端返回报错信息)
  • 直接在方法queryDeptById()上加上注解@HystrixCommand,这个注解需要传递一个参数fallbackMethod,即失败的时候调用的方法的名称
@HystrixCommand(fallbackMethod = "hystrixQueryDeptById")
@GetMapping("/dept/queryById/{deptno}")
public Dept queryDeptById(@PathVariable("deptno") long id){
//原来服务者提供的按照id查询部门信息的方法,不做任何修改,只是加上注解@HystrixCommand
//和一个判断获取到的dept对象是否为null,如果为null直接手动抛出异常
    Dept dept = deptService.queryDeptById(id);
    if (dept==null){	
    //注意:这个异常抛出必须有,否则hystrix不能发现这个方法执行的时候出现了异常
        throw new RuntimeException("这个id====>"+id+"对应的部门不存在,或信息无法找到~");
    }
    return dept;
}


public Dept hystrixQueryDeptById(@PathVariable("deptno") long id){
//这个方法就是hystrix用于在上面提供的按照id查询部门信息的方法崩溃/报错的时候替换它继续提供服务的方法
    return new Dept()
            .setDeptno(id)
            .setDname("抱歉,未查询到您指定的id对应的部门信息")
            .setDb_source("MySQL数据库中没有匹配的数据库存有查询的信息");
}
  • 注意:我们定义的hystrix用于在原来服务者提供的按照id查询部门信息的方法崩溃/报错的时候替换它继续提供服务的方法的定义除了方法名称,其他的应该和原方法保持一致,这是为了返回的数据仍是原来的数据类型;上面熔断处理方法返回的是一个我们临时new出来的Dept对象,这个对象的属性都是我们设置的提示信息,用于正常的结束本次消费者对于服务的请求并返回给消费者提示信息
  • 注意:上面我们直接返回一个消费者期望的Dept对象,或者说是原服务相同的数据类型的数据,比我们直接抛出异常然后再捕获异常再返回给消费者来的好
  • 注意:异常抛出必须有,否则hystrix不能发现这个方法执行的时候出现了异常
  • 去这个model的入口程序/主启动类上加上注解@EnableXXX
package com.thhh.springcould;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient //标识这是一个eureka注册中心提供服务的客户端,加上配置文件中配置的注册中心的url,服务就会被自动注册到eureka注册中心中去
@EnableCircuitBreaker//开启熔断器,即添加对熔断的支持
public class HystrixDeptProvider_8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDeptProvider_8001.class,args);
    }
}
  • 测试效果

Spring cloud gateway 熔断 降级_分布式_05


Spring cloud gateway 熔断 降级_分布式_06


Spring cloud gateway 熔断 降级_Hystrix_07


Spring cloud gateway 熔断 降级_服务熔断_08

  • 使用Hystrix实现熔断机制虽然效果很好,但是加大了增高开发的代码量,因为服务者每新增一个向外体提供服务的方法,我们就需要对应的为这个方法新增一个hystrix的熔断机制的备份方法,或许可以出现多个方法使用一个hystrix的熔断机制的备份方法,但是大多数情况下我们还是要针对不同的情境返回不同的提示信息,所以代码量还是会增高

3.显式提供服务的服务器的IP

Spring cloud gateway 熔断 降级_Hystrix_09


Spring cloud gateway 熔断 降级_分布式_10


Spring cloud gateway 熔断 降级_Hystrix_11


4.小结

  • Hystrix使用步骤
  • 编写hystrix熔断之后的备用方法
  • 使用注解@HystrixCommand指定熔断之后调用的方法的名称
  • 使用注解@EnableCircuitBreaker开启model的熔断器
  • Hystrix对于用户体验更好,但是代码量增加
  • 可以修改监控页面上对应的服务的Status字段下面超链接显示的地址为IP,而不是localhostXXX