Hystrix使用概述

349 阅读4分钟

Hystrix简介

  在分布式系统中,总有些依赖服务会不可避免的发生错误。如果任由这些错误或者卡顿存在下去,很可能使得整个请求链失败,进而导致整个系统瘫痪。Hystrix是一个可以帮助在分布式系统中通过延迟和容错来解决这个问题的库,他能够通过隔离各个服务,防止级联错误,他允许自定义调用失败后的方法,以增强系统的弹性。

用法

Hystrix用法有很多,本文只讲解其中两种。
首先肯定是引入依赖(默认已集成Feign,Nacos或Euraka)

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

在启动类上加开启hystrix的注解

@EnableHystrix

在配置文件中开启

feign: 
  hystrix:
    enabled: true

下面就可以使用了

1. 使用注解

使用@HystrixCommand注解,写在将要调用关联系统的方法上,当调用时满足条件后将会走hystrix。看下列代码

@HystrixCommand(fallbackMethod= "fallback_test",commandProperties = {
        //false参数表示默认不开启熔断,达到条件才会开启
        @HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
        //设置这个线程的超时时间是3s,3s内是正常的业务逻辑,超过3s调用fallbackMethod指定的方法进行处理
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "10000"),
        //失败次数达到多少后跳闸(即开启熔断,开启后会拒绝所有请求,并跳转到fallbackmethod),必须与失败率与结合起来使用
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
        //失败率达到多少后跳闸,必须与失败次数与结合起来使用
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
        //xx毫秒后熔断进去半开状态,放一个请求过来,如果能执行成功,就关闭熔断,否则继续等待xx毫秒后再进入半开状态
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
})
public String test(String name) throws InterruptedException {
    System.out.println("p2 service");
    return p1TestFeign.test(name);
}

fallbackMethod的值就是调用失败后,自定义的调用的本地的方法,这个方法必须写在这个类里面才能够找到,且fallback_test方法的参数必须与test方法参数相同(即方法签名相同)。 如果类中有多个方法都需要用上该注解,每个都写@HystrixCommand就会很麻烦,那么就可以在类上写类似的注解(注意是类似的,而不是一样的)。

@DefaultProperties(defaultFallback= "defaultFallback",commandProperties = {
        //false参数表示默认不开启熔断,达到条件才会开启
        @HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
        //设置这个线程的超时时间是3s,3s内是正常的业务逻辑,超过3s调用fallbackMethod指定的方法进行处理
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "10000"),
        //失败次数达到多少后跳闸(即开启熔断,开启后会拒绝所有请求,并跳转到fallbackmethod),必须与失败率与结合起来使用
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
        //失败率达到多少后跳闸,必须与失败次数与结合起来使用
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
        //xx毫秒后熔断进去半开状态,放一个请求过来,如果能执行成功,就关闭熔断,否则继续等待xx毫秒后再进入半开状态
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
})

可以同时在类上和方法上写注解,会优先使用方法上的注解。注意defaultFallback方法不能有参数,其返回类型需与类中方法的返回类型兼容。

2. 使用侵入式代码

首先构建一个类,继承HystrixCommand类,写一个构造方法,将调用远程系统所用的参数传递进来并保存。写run()方法,方法中内容就是用来进行远程调用。再写覆写一个getFallback()方法,当远程调用出错或者超时等问题发生后,将会调用这个方法。

public class CommandHelloWorld extends HystrixCommand<String> {

    private String name = "";

    P1TestFeign p1TestFeign;

    public CommandHelloWorld(String name, P1TestFeign p1TestFeign) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        /*super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(5000)
                .withCircuitBreakerErrorThresholdPercentage(50)
                .withCircuitBreakerRequestVolumeThreshold(5)
                .withCircuitBreakerForceOpen(false)));*/
        this.name = name;
        this.p1TestFeign = p1TestFeign;
    }

    protected String run() throws InterruptedException {
        // a real example would do work like a network call here
        return p1TestFeign.test(name);
    }

    @Override
    protected String getFallback() {
        return "熔断->" + name + "!";
    }
}

构造方法中, super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));是使用默认的配置,建议使用注释部分的设置,可以指定断路降级的策略,其用法与注解处是一样的。

总结

  其实我个人没搞懂hystrix为何要提供侵入式代码使用方法,因为注解方法已经能够解决问题了,而且很好用。我个人建议也是大家在使用的时候可以尽量使用注解的方式。