结合函数式接口 Supplier 使用熔断器 Hystrix

前言

如果你只需要使用 Hystrix 的注解形式就够了,那本篇文章对你没什么意义,但如果是采用继承 HystrixCommand 类进行使用,可以结合函数式接口 Supplier 进行更解耦的实现,对业务的侵入小,并且代码的相互依赖低

代码

我们先来看一段代码

private Boolean equal(String s1, String s2) {
    return equalStr(s1, s2);
}

private Boolean equalStr(String s1, String s2) {
    return s1.equals(s2);
}

只采用继承 HystrixCommand 类进行使用

如果你直接把这段代码采用继承 HystrixCommand 类进行使用,并且用s1作为熔断标识

private Boolean equal(String s1, String s2) {
    return new StrCommand(s1, s2).execute();
}
public class StrCommand extends HystrixCommand<Boolean> {

    private String s1;
    private String s2;

    public StrCommand(String s1, String s2) {
    		// 熔断标识
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(s1))
                .andCommandKey(HystrixCommandKey.Factory.asKey(s1))
                .andCommandPropertiesDefaults(
                        // 熔断超时时间
                        HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(Config.OUT_TIME)
                                // 单位统计时间
                                .withMetricsRollingStatisticalWindowInMilliseconds(Config.WINDOW_TIME)
                                // 统计请求数量阈值
                                .withCircuitBreakerRequestVolumeThreshold(Config.NUMBER_OF_REQUESTS)
                                // 错误百分比
                                .withCircuitBreakerErrorThresholdPercentage(Config.ERROR_PERCENTAGE)
                                // 休眠时间
                                .withCircuitBreakerSleepWindowInMilliseconds(Config.SLEEP_TIME)));
        this.s1 = s1;
        this.s2 = s2;
    }

    @Override
    protected Boolean run() throws Exception {
        return s1.equals(s2);
    }
    @Override
    protected Boolean getFallback() {
        System.out.println("熔断");
        return false;
    }
}

有注意到吗,你需要把整个equalStr重构为 HystrixCommand 类,不仅要把整个原来的逻辑挪出来,而且 HystrixCommand 类里的属性也很多,这把业务性代码和功能性代码揉到一起,对于后续的其他实现也有影响,所以,我们不妨结合函数式接口 Supplier 进行更解耦的实现

结合函数式接口 Supplier

private Boolean equal(String s1, String s2) {
    Supplier<Boolean> supplier = () -> equalStr(s1, s2);
    return new StrCommand(supplier).execute();
}

private Boolean equalStr(String s1, String s2) {
    return s1.equals(s2);
}
public class StrCommand extends HystrixCommand<Boolean> {
    private Supplier<Boolean> supplier;

    public StrCommand(Supplier supplier) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(s1))
                .andCommandKey(HystrixCommandKey.Factory.asKey(s1))
                .andCommandPropertiesDefaults(
                        // 熔断超时时间
                        HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(Config.OUT_TIME)
                                // 单位统计时间
                                .withMetricsRollingStatisticalWindowInMilliseconds(Config.WINDOW_TIME)
                                // 统计请求数量阈值
                                .withCircuitBreakerRequestVolumeThreshold(Config.NUMBER_OF_REQUESTS)
                                // 错误百分比
                                .withCircuitBreakerErrorThresholdPercentage(Config.ERROR_PERCENTAGE)
                                // 休眠时间
                                .withCircuitBreakerSleepWindowInMilliseconds(Config.SLEEP_TIME)));
        this.supplier = supplier;
    }

    @Override
    protected Boolean run() throws Exception {
        return supplier.get();
    }
    @Override
    protected Boolean getFallback() {
        System.out.println("熔断");
        return false;
    }
}

看到了吗,这样业务性代码和功能性代码就完全隔离开来,后续无论是要调整熔断,还是要改进原来的业务代码,双方都没有影响,这就是更优雅的实现

希望有所帮助,完