Hystrix-断路器核心原理

0. 前言

  • SpringBoot版本:2.1.9.RELEASE
  • SpringCloud版本:Greenwich.SR4

1. HystrixCircuitBreaker

public interface HystrixCircuitBreaker {

    // 是否允许请求
    public boolean allowRequest();

    // 断路器是否开启
    public boolean isOpen();

    // 关闭断路器
    void markSuccess();

}

2. HystrixCircuitBreakerImpl

static class HystrixCircuitBreakerImpl implements HystrixCircuitBreaker {
  
    // 熔断配置信息
    private final HystrixCommandProperties properties;
  
    // 熔断指标信息
    private final HystrixCommandMetrics metrics;

    // 断路器是否开启
    private AtomicBoolean circuitOpen = new AtomicBoolean(false);

    // 记录断路器开启或最近测试请求时间
    private AtomicLong circuitOpenedOrLastTestedTime = new AtomicLong();

    protected HystrixCircuitBreakerImpl(HystrixCommandKey key, HystrixCommandGroupKey commandGroup, HystrixCommandProperties properties, HystrixCommandMetrics metrics) {
        this.properties = properties;
        this.metrics = metrics;
    }

    public void markSuccess() {
        if (circuitOpen.get()) {
            // 如果断路器开启,则关闭
            if (circuitOpen.compareAndSet(true, false)) {
                // 重置熔断指标信息
                metrics.resetStream();
            }
        }
    }

    @Override
    public boolean allowRequest() {
        if (properties.circuitBreakerForceOpen().get()) {
            // 如果配置了断路器强制开启,返回 false 不允许发起请求
            return false;
        }
        if (properties.circuitBreakerForceClosed().get()) {
            // 如果配置了断路器强制关闭,返回 true 允许发起请求
            // 但是还是要调用 isOpen() 方法处理断路器相关信息
            isOpen();
            return true;
        }
        // 两个条件满足其一则允许请求:
        //     1. 断路器认为是关闭的
        //     2. 允许尝试一次请求
        return !isOpen() || allowSingleTest();
    }

    public boolean allowSingleTest() {
        long timeCircuitOpenedOrWasLastTested = circuitOpenedOrLastTestedTime.get();
        if (circuitOpen.get() && System.currentTimeMillis() > timeCircuitOpenedOrWasLastTested + properties.circuitBreakerSleepWindowInMilliseconds().get()) {
            if (circuitOpenedOrLastTestedTime.compareAndSet(timeCircuitOpenedOrWasLastTested, System.currentTimeMillis())) {
                // 断路器开启后,每隔一定时间(默认5s)允许尝试一次请求
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean isOpen() {
        if (circuitOpen.get()) {
            // 断路器开启,返回 true
            return true;
        }

        // 获取健康指标信息
        HealthCounts health = metrics.getHealthCounts();

        if (health.getTotalRequests() < properties.circuitBreakerRequestVolumeThreshold().get()) {
            // 如果在最近10s(默认)请求总数小于20次(默认)
            // 则认为断路器是关闭的
            return false;
        }

        if (health.getErrorPercentage() < properties.circuitBreakerErrorThresholdPercentage().get()) {
            // 如果在最近10s(默认)请求失败率小于50%(默认)
            // 则认为断路器是关闭的 
            return false;
        } else {
            // 记录断路器状态为开启
            if (circuitOpen.compareAndSet(false, true)) {
                circuitOpenedOrLastTestedTime.set(System.currentTimeMillis());
                return true;
            } else {
                return true;
            }
        }
    }

}

3. 总结

  • 断路规则:

    断路规则图

  • 断路器开启后,单位时间内允许尝试一次请求:

    单线程单请求

    学习参考:掘金小册《SpringCloudNetflix 源码解读与原理分析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值