Hystrix组件

在分布式环境中,许多服务依赖项不可避免地会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止它们之间的级联故障以及提供后备选项来实现这一点,所有这些都可以提高系统的整体弹性。

通俗定义: Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩现象),提高分布式系统的弹性。

Hystrix 用来保护微服务系统实现服务降级、服务熔断

服务雪崩

在微服务之间进行服务调用时由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程。

调用链路:

img点击并拖拽以移动

Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用

img点击并拖拽以移动

服务熔断

服务熔断能够很好地防止服务雪崩现象

“熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器(hystrix)的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。 如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段

img点击并拖拽以移动

熔断机制:

所有的微服务中必须引入Hystrix组件用来监控,一旦引入Hystrix组件,这个组件就具有服务熔断功能。

服务降级

服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此缓解服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的响应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。

img点击并拖拽以移动

服务降级: 关闭微服务系统中某些无用的边缘服务,让系统专注于处理核心服务中的的请求,保证系统核心服务正常运行

降级和熔断的总结

共同点

  • 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
  • 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
  • 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
  • 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;sentinel

不同点

  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
  • 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务边缘服务开始)

熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理

服务熔断的实现

1.每个微服务项目中引入Hystrix依赖

<!--引入hystrix-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
server.port=8990
spring.application.name=HYSTRIX

# 注册到consul server 上
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

2.开启熔断功能:在入口类加入注解

@SpringBootApplication  //代表springboot应用
@EnableDiscoveryClient  //代表服务注册中心客户端   consul  client
@EnableCircuitBreaker   //开启hystrix服务熔断
public class HystrixApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixApplication.class,args);
    }
}

3.使用HystrixCommand注解实现断路,在控制器方法中加入备选处理方法

@RestController
public class DemoController {
    @GetMapping("demo")
    //@HystrixCommand注解是方法级别的,加在你需要捕获监控的方法
    //熔断之后或调用失败的处理(要执行的方法):fallbackMethod 注:方法的参数列表和返回值类型要和熔断的方法一致
    @HystrixCommand(fallbackMethod = "DemoFallBack" )
    public String demo(Integer id){
        if(id<=0){
            throw new RuntimeException("无效ID");
        }
        return "Demo ok";
    }
    //熔断之后的备选处理
    public String DemoFallBack(Integer id){
        return "Id:"+id+"当前服务被熔断了";
    }
}

4.测试

返回值:
Demo ok,id:1
返回值:
Id:-1当前服务被熔断了

然后再用正确参数访问:http://localhost:8990/demo?id=1
返回值:
Id:-1当前服务被熔断了

过5s后再用正确参数访问:localhost:8990/demo?id=1
返回值:
Demo ok,id:1

发现如果触发一定条件断路器会自动打开,过了一点时间正常之后又会关闭。

熔断原理:

  • 1当满足一定的阀值的时候(默认10秒内超过20个请求次数)
  • 2当失败率达到一定的时候(默认10秒内超过50%的请求失败)
  • 3到达以上阀值,断路器将会开启
  • 4当开启的时候,所有请求都不会进行转发
  • 5 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5。 img点击并拖拽以移动

默认FallBack

如果FallBack处理大同小异,为每一个服务方法开发一个降级,对于我们来说,可能会出现大量的代码的冗余,不利于维护,这个时候就需要加入默认服务降级处理方法

//默认的处理方法
  public String defaultFallBack(){
      return "网络连接失败,请重试!!!";
  }
//fallbackMethod换为defaultFallback即可,以后所有的方法都可这样写来采用同一处理方法
@HystrixCommand(defaultFallback = "defaultFallBack" )

服务降级的实现

客户端openfeign + hystrix实现服务降级实现

1.依赖的引入

注:OpenFeign组件的底层集成了Hytrix依赖,若引入OpenFeign的依赖则无需在引入Hytrix依赖

2.开启openfeign支持服务降级

server.port=8991
spring.application.name=OPENFEIGNHYSTRIX

#注册服务中心
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500

# 开启openfeign在调用服务过程中 开启hystrix支持 默认:就是没有开启
feign.hystrix.enabled=true

3.开发OpenFeign服务调用失败默认的处理实现类

// 自定义HystrixClient 默认备选处理
@Configuration
public class HystrixClientFallBack implements HystrixClient {
    
    @Override
    public String demo(Integer id) {
        return "当前服务不可用,请稍后再试! id: "+id;
    }
}

4.Feign接口,除了要指明要调用的服务,还要通过fallback指明调用失败时的处理类(即使要调用的服务有Hystrix熔断器,但是当服务整个宕掉,熔断器此时也会变的不可用,需要该类来进行处理)


@FeignClient(value = "HYSTRIX",fallback = HystrixClientFallBack.class)
//------fallback: 这个属性用来指定当前要调用的服务完全不可用(宕掉)时,默认的备选处理--------
public interface HystrixClient {
    @GetMapping("/demo")
    String demo(@RequestParam("id") Integer id);
}

5.Controller

@RestController
public class TestController {
    //注入openfeign 客户端对象
    @Autowired
    private HystrixClient hystrixClient;

    @GetMapping("test")
    public String test(Integer id){
        System.out.println("test ok !!!");
        String demoResult = hystrixClient.demo(id);
        System.out.println("demo result : "+demoResult);
        System.out.println("后续业务逻辑");
  //如果在调用的服务中不添加熔断器,那么调用出错后,程序根本走不到这一步,正因为在调用的服务方法发生错误时,   //熔断器会将其熔断,并通过fallbackMethod返回一个处理结果,使得当前程序可以继续执行,而不是长时间的等     //待或者抛出无法处理的异常
        return demoResult;
    }
}

测试:

正确参数: localhost:8991/test?id=1

返回值:
Demo ok,id:1

错误参数: localhost:8991/test?id=-1

返回值:
Id:-1当前服务被熔断了
反复用错误参数访问: localhost:8991/test?id=-1
返回值:
Id:-1当前服务被熔断了

然后再用正确参数访问:localhost:8991/test?id=1
返回值:
Id:-1当前服务被熔断了

过5s后再用正确参数访问:localhost:8991/test?id=1
返回值:
Demo ok,id:1

把Hytrix服务关掉在测试: localhost:8991/test?id=-1

返回值:
当前服务不可用,请稍后再试! id: -1

可以发现执行了自定义的调用失败的处理实现类

Hystrix DashBoard

监控每一个@Hystrixcommond注解创建一组度量,构建一组信息,然后通过图形化方式展示当前方法 @HystrixCommond的状态信息,显示每个断路器的运行状况。

创建一个独立的DashBoard的SpringBoot应用:

1.引入依赖:

<!--引入hystrix dashboard 依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

2.入口类中开启hystrix dashboard

@SpringBootApplication
//@EnableDiscoveryClient  //注意: 默认只要引入discovery client依赖 该注解无须显示声明 自动注册 consul zk nacos
@EnableHystrixDashboard   //注意: 这个注解作用用来开启当前应用为仪表盘应用
public class HystrixDashBoardApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashBoardApplication.class,args);
    }

3.启动hystrix dashboard应用

http://localhost:9909(端口)/hystrix

img点击并拖拽以移动

4.在要监控的项目中入口类中加入监控路径配置[新版本坑],并启动监控项目

@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;
}

还有个bug

# 解决方案
- 新版本中springcloud将jquery版本升级为3.4.1,定位到monitor.ftlh文件中,js的写法如下:
	$(window).load(function() 	
- jquery 3.4.1已经废弃上面写法
                   
- 修改方案 修改monitor.ftlh为如下调用方式:
	$(window).on("load",function()	
                 
- 编译jar源文件,重新打包引入后,界面正常响应。

已修改完的jar包:

https://sovzn.lanzoui.com/iOHo5tdsqhi
密码:a9xw

Hystrix停止更新维护了