SpringCloud之Hystrix

发布时间 2023-04-02 16:16:39作者: shigp1

spring cloud 用的是 hystrix,是一个容错组件。

Hystrix实现了 超时机制和断路器模式。

Hystrix是Netflix开源的一个类库,用于隔离远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。主要有以下几点功能:

  1. 为系统提供保护机制。在依赖的服务出现高延迟或失败时,为系统提供保护和控制。
  2. 防止雪崩。
  3. 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中运行。
  4. 跳闸机制:当某服务失败率达到一定的阈值时,Hystrix可以自动跳闸,停止请求该服务一段时间。
  5. 资源隔离:Hystrix为每个请求都的依赖都维护了一个小型线程池,如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。防止级联失败。
  6. 快速失败:Fail Fast。同时能快速恢复。侧重点是:(不去真正的请求服务,发生异常再返回),而是直接失败。
  7. 监控:Hystrix可以实时监控运行指标和配置的变化,提供近实时的监控、报警、运维控制。
  8. 回退机制:fallback,当请求失败、超时、被拒绝,或当断路器被打开时,执行回退逻辑。回退逻辑我们自定义,提供优雅的服务降级。
  9. 自我修复:断路器打开一段时间后,会自动进入“半开”状态,可以进行打开,关闭,半开状态的转换。

整合Resttemplate

在ConsumerByRibbon模块加入依赖:

  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

在启动类加@EnableCircuitBreaker。

 

controller增加测试方法:

@HystrixCommand(fallbackMethod = "fail")
@RequestMapping("/helloByTemplate")
public String helloByTemplate() {
     return restTemplate.getForObject("http://producer/hello", String.class);
}


public String fail() {
    return "请求失败";
}

fallbackMethod指定请求失败时服务降级执行方法名。

 

不启动Producer,访问http://localhost:8003/helloByTemplate,看到:

请求失败

整合Feign

在application.properties配置:

feign.hystrix.enabled=true

HelloFeign改成:

@FeignClient(value = "producer",fallback = HelloFeignFallBack.class)
public interface HelloFeign {
    @RequestMapping("/hello")
    public String hello(@RequestParam String name);
}

增加fallback属性。

@Component
public class HelloFeignFallBack implements HelloFeign{
    @Override
    public String hello(String name) {
        return "请求失败了";
    }
}

HelloFeignFallBack要实现HelloFeign接口,且要加@Component注解。

 

访问http://localhost:8003/helloByFeign,看到

请求失败了

 

如果要获取调用服务发生异常的类型,要使用FallbackFactory。

@Component
public class HelloFeignFallBackFactory implements FallbackFactory<HelloFeign> {
    @Override
    public HelloFeign create(Throwable throwable) {
        return new HelloFeign() {
            @Override
            public String hello(String name) {
                throwable.printStackTrace();
                return "出现异常";
            }
        };
    }
}

服务降低处理类要实现FallbackFactory接口。

 

修改HelloFeign:

@FeignClient(value = "producer",fallbackFactory = HelloFeignFallBackFactory.class)
public interface HelloFeign {
    @RequestMapping("/hello")
    public String hello(@RequestParam String name);
}

信号量隔离与线程隔离

默认情况下hystrix使用线程池控制请求隔离

线程池隔离技术,是用 Hystrix 自己的线程去执行调用;而信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。
 
 
 
信号量隔离主要维护的是Tomcat的线程,不需要内部线程池,更加轻量级。

 

修改成信号量隔离,在application.properties配置:

hystrix.command.default.execution.isolation.strategy=SEMAPHORE

线程池隔离的优点:
1.隔离服务的依赖,请求线程可以快速放回
2.当其他线程池出现问题时候,线程池是独立的,不会影响其他服务和接口
3.当服务从不可用状态变为可用状态时,线程池将清理并立即恢复,而不需要一个长时间的恢复
4.独立的线程池提高了线程的并发性

线程池隔离的缺点:
增加了cpu的计算开销,每个命令涉及到的排队,调度,上下文切换都是在一个单独的线程上运行的

 

信号量隔离优点:
资源消耗小,不需要线程池,轻量级。

缺点:
信号量隔离的执行线程是web容器的线程,如果执行时间较长,会影响web容器的并发。且调用出现问题会影响web容器线程。

 

开启dashboard

ConsumerByRibbon模块添加依赖:

     <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

启动类添加@EnableHystrixDashboard。

先将hystrix.command.default.execution.isolation.strategy=SEMAPHORE注释,在application.properties配合开启actuator端点:

management.endpoints.web.exposure.include=*
hystrix.dashboard.proxy-stream-allow-list=localhost

hystrix.dashboard.proxy-stream-allow-list配置开启HystrixDashboard图形化接口对监控的代理地址。
 

访问http://localhost:8003/actuator/hystrix.stream,看到:

 

访问http://localhost:8003/helloByFeign后在访问http://localhost:8003/actuator/hystrix.stream看到:

 

访问图形化接口http://localhost:8003/hystrix,

 

并填入http://localhost:8003/actuator/hystrix.stream,点击monitor stream。看到:

 
启动Producer,访问http://localhost:8003/helloByFeign,再看看http://localhost:8003/hystrix:

 
在application.properties开启hystrix.command.default.execution.isolation.strategy=SEMAPHORE,访问http://localhost:8003/helloByFeign,再看看http://localhost:8003/hystrix:

可以看到信号隔离没有线程池。