熔断器的原理与代码分析

代码

https://blog.csdn.net/jfwan/article/details/109328874

原理与代码分析

核心参数

Total – 向下游发送的总请求量

Accept – 下游能正常返回的请求量

在算法设计中,Total和Accept之间存在一个倍数,当total大于Accept乘以这个倍数,则表示下游服务出现异常,熔断功能打开。否则会将请求直接发往下游服务。这个倍数就是下面结构体中的参数k。

type googleBreaker struct {
	k     float64
	stat  *collection.RollingWindow
	proba *mathx.Proba
}

如何判断是否往下游发放请求量由下面函数实现

func (b *googleBreaker) accept() error {
	accepts, total := b.history()
	weightedAccepts := b.k * float64(accepts)
	// https://landing.google.com/sre/sre-book/chapters/handling-overload/#eq2101
	dropRatio := math.Max(0, (float64(total-protection)-weightedAccepts)/float64(total+1))
	if dropRatio <= 0 {
		return nil
	}

	if b.proba.TrueOnProba(dropRatio) {
		return ErrServiceUnavailable
	}

	return nil
}

Accepts和total分别是窗口期内正常返回的请求量和总请求量。Protection是一个常量值,它的作用是当窗口期内的请求数量较少时,我们默认不打开熔断器(因为对下游的压力很小),同时也为后续的流量熔断判断作为依据。当weightedAccepts远小于total时(下游请求大量异常的情况),dropRatio的值接近1;当weightedAccepts接近甚至大于total时,dropRatio的值接近0。我们再来看b.proba.TrueOnProba的实现

func (p *Proba) TrueOnProba(proba float64) (truth bool) {
	p.lock.Lock()
	truth = p.r.Float64() < proba
	p.lock.Unlock()
	return
}

p.r.Float64()计算结果是0到1的一个随机值,因此dropRatio的值接近1时请求大概率会被熔断器给拦截掉。

我们再来看一下accepts和total是如何计算出来的。它的核心思想就是将时间窗口分为若干个小的窗口,将每个小窗口的accepts和total取和。比如源代码实现的时间窗口为10s,细分了40份小的窗口,每个小窗口的时间跨度为250ms。我们统计最近10s内的下游响应情况,以此为依据判断是否打开熔断器,这比较好理解。那为何要划分40个窗口呢?原因是作者希望找到最近10s内的值,因此只用选取从当前时间点开始倒推40个小窗口值的和,细分的作用就是模拟取值窗口的平滑移动。这部分的细节代码在rollingwindow.go文件中。

判断熔断器是否允许向下游发送请求,由下面的函数进行实现

func (b *googleBreaker) allow() (internalPromise, error) {
	if err := b.accept(); err != nil {
		return nil, err
	}

	return googlePromise{
		b: b,
	}, nil
}

它返回了一个Promise结构的参数,这个结构有两个默认的方法

Promise interface {
		// Accept tells the Breaker that the call is successful.
		Accept()
		// Reject tells the Breaker that the call is failed.
		Reject(reason string)
	}

当本次下游返回成功后会调用Accept方法,否则会调用Reject方法。这两个方法的调用会加入细分窗口的accepts和total的值,为之后熔断器判断作运算基础。

参考文献

https://blog.csdn.net/jfwan/article/details/109328874

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值