SpringCloud Hysyrix熔断器

前言

Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失 败,从而提升系统的可用性与容错性,Hystrix主要通过以下几点实现延迟和容错

  • 包裹请求:使用HystrixCommmand封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中,这个访问请求一般会运行在独立的线程中,资源隔离
  • 跳闸机制:对于超出我们设定阈值的服务调用,直接进行超时,不允许其耗费过长时间阻塞住
  • 资源隔离:每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队阻塞等待,从而加速失败判定。
  • 服务监控:可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝 的请求等。
  • 降级机制:当一个服务调用出现失败,被拒绝,超时,短路等异常情况时,自动调用fallback降级机制

Rest实现服务熔断

引入依赖

还是使用我们前面文章的例子 在shop_service_order中引入Hystrix的依赖

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

开启熔断

在启动类上添加@EnableCircuitBreaker 注解开启对熔断器的支持

配置熔断降级业务逻辑

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    @HystrixCommand(fallbackMethod = "orderFallBack")
    public Product order(@PathVariable Long id) {
        return restTemplate.getForObject("http://shop-service-product/product/1", Product.class);
    }

    //降级方法
    public Product orderFallBack(Long id) {
        Product product = new Product();
        product.setProductName("触发熔断降级方法");
        return product;
    }
}

order下单方法添加一个降级回退方法orderFallBack,该方法和order方法参数与返回类型需一致,该方法返回一个默认的错误信息,在order方法上使用注解@HystrixCommandfallbackMethod属性指定熔断触发的降级方法


当商品微服务正常的时候,可以通过浏览器访问 下单接口,如果当商品服务关闭不能提供数据的时候,就会触发我们设置好的熔断降级方法

配置默认的Fallback

上面我们把fallback配置在了某个业务方法上,如果业务方法很多每个业务方法都得配置一个fallback,所以我们可以把fallback配置加在类上,实现默认的fullback

@DefaultProperties(defaultFallback = "orderFallBack")

超时配置

在上面的案例中,请求在超时1秒后就会返回错误信息,这是因为Hystrix的默认超时时间为1秒,我们可以 通过配置修改这个值:

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000

Feign实现服务熔断

SpringCloud Fegin默认已为Feign整合了hystrix,所以添加Feign依赖后就不用在添加hystrix依赖,那么怎么才能让Feign的熔断机制生效呢,只要按以下步骤开发:

修改yml配置

在Feign中已经内置了hystrix,但是默认是关闭的需要在工程的 application.yml 中开启对hystrix的 支持

feign:
  hystrix:
    enabled: true

配置FeignClient接口实现类

基于Feign实现熔断降级,那么降级方法需要配置到FeignClient接口的实现类中

@Component
public class ProductFeignClientCallBack implements ProductFeignClient {

    /**
     * 降级方法
     */
    @Override
    public Product findById(Long id) {
        Product product = new Product();
        product.setProductName("触发熔断降级方法");
        return product;
    }
    
}

配置FeignClient

在@FeignClient注解中添加降级方法,@FeignClient 注解中以fallback声明降级类

//指定需要调用的微服务名称
@FeignClient(name = "shop-service-product",fallback = ProductFeignClientCallBack.class)
public interface ProductFeignClient {

    //调用的请求路径
    @RequestMapping(value = "/product/{id}",method = RequestMethod.GET)
    public Product findById(@PathVariable("id") Long id);

}

Hystrix监控平台搭建

除了实现容错功能,Hystrix还提供了近乎实时的监控,HystrixCommand和 HystrixObservableCommand在执行时,会生成执行结果和运行指标。比如每秒的请求数量,成功数 量等。这些状态会暴露在Actuator提供的/health端点中。
只需为项目添加 spring-boot-actuator依赖

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

重启项目,访问http://localhost:9001/actuator/hystrix.stream 即可看到实时的监控数据。
访问后你看到的页面可能会报错(404)


我们可以通过 http://localhost:9001/actuator看到其中并没有hystrix.stream接口

我们需要在yml中进行一个配置暴露全部端点,这样一来就OK了,接下来就开始搭建监控平台

management:
  endpoints:
    web:
      exposure:
        include: '*'

导入依赖

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

添加注解

在启动类使用@EnableHystrixDashboard注解激活仪表盘项目,重启微服务

访问测试

http://localhost:9002/hystrix


输入微服务监控端点地址,点击Monitor即可看到监控数据

断路器聚合监控

在微服务架构体系中,每个服务都需要配置Hystrix DashBoard监控。如果每次只能查看单个实例的监 控数据,就需要不断切换监控地址,这样并不方便,要看Hystrix Dashboard数据就需要切换到那个,Turbine是一个聚合Hystrix 监控数据的工具,他可以将所有相关微服务的 Hystrix 监控数据聚合到一起,方便查看。引入Turbine后,整个监控系统架构如下:

搭建TurbineServer

创建工程 shop_hystrix_turbine 并且引入相关坐标

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

配置hystrix监控

在application.yml的配置文件中开启turbine并进行相关配置

server:
  port: 8031
spring:
  application:
    name: shop_hystrix_turbine

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
  instance:
    prefer-ip-address: true #使用ip注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册的服务id

turbine:
  app-config: shop-service-order #要监控的微服务列表,多个用,分隔
  cluster-name-expression: "'default'"

Eureka相关配置:指定注册中心地址turbine会自动的从注册中心中获取需要监控的微服务,并聚合所有微服务中的 /hystrix.stream 数据
Turbine相关配置:指定需要监控的微服务列表

配置启动类

@SpringBootApplication
@EnableTurbine
@EnableHystrixDashboard
public class TurbinServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(TurbinServerApplication.class,args);
    }
}

作为一个独立的监控项目,需要配置启动类,开启 HystrixDashboard监控平台,并激活Turbine

测试

浏览器访问 http://localhost:8031/hystrix 展示HystrixDashboard。并在url位置输入 http://local host:8031/turbine.stream ,动态根据turbine.stream数据展示多个微服务的监控数据

熔断器的状态

熔断器有三个状态CLOSEDOPENHALF_OPEN,熔断器默认关闭状态,当触发熔断后状态变更为 OPEN ,等待到指定的时候后,Hystrix会放请求检测服务是否开启,这期间熔断器会变为 HALF_OPEN 半 开启状态,如果熔断器检测到服务可用则变更状态为CLOSED关闭熔断器、如不可用则继续上述步骤。


Closed:关闭状态(断路器关闭),所有请求均可正常访问,代理类维护了最近调用失败的次数, 如果某次调用失败,则使失败次数加1。如果最近失败次数超过了在给定时间内允许失败的阈值, 则代理类切换到断开(Open)状态,此时代理开启了一个超时时钟,当该时钟超过了该时间,则切 换到半断开(Half-Open)状态。该超时时间的设定是给了系统一次机会来修正导致调用失败的错误。

Open:打开状态(断路器打开)所有请求都会被降级。Hystix会对请求情况计数,当一定时间 内失败请求百分比达到阈值,则触发熔断,默认失败比例的阈值是50%,请求次数最少不低于20次。

Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路 器会自动进入半开状态。此时会释放1次请求通过,若这个请求是健康的,则会关闭断路器,否则 继续保持打开,再次进行5秒休眠计时。

熔断器触发状态配置

熔断器的默认触发阈值是20次请求,失败占比50%就触发熔断降级,我们可以通过以下配置修改默认配置

#触发熔断的最小请求次数,默认20 
circuitBreaker.requestVolumeThreshold=5 
#触发熔断的失败请求最小占比,默认50% 
circuitBreaker.sleepWindowInMilliseconds=10000 
#熔断多少秒后去尝试请求
circuitBreaker.errorThresholdPercentage=5 

熔断器的隔离策略

微服务使用Hystrix熔断器实现了服务的自动降级,让微服务具备自我保护的能力,提升了系统的稳定性,也较好的解决雪崩效应。其使用方式目前支持两种策略:

  • 线程池隔离策略:使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)
  • 信号量隔离策略:使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判 断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请 求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)

两种隔离策略功能对比

功能线程池隔离信号量隔离
线程与调用线程非相同线程与调用线程为同一个线程(jetty线程)
开销排队、调度、上下文开销等无线程切换,开销低
异步支持不支持
并发支持支持(最大线程池大小)支持(最大信号量上线)

隔离策略配置

#配置隔离策略
hystrix.command.default.execution.isolation.strategy =
# ExecutionIsolationStrategy.THREAD 线程池隔离
# ExecutionIsolationStrategy.SEMAPHORE 信号量隔离
# hystrix.command.default.execution.isolation.maxConcurrentRequests : 最大信号量上限

添加新评论

评论列表