应对过载- go-zero源码阅读

5 篇文章 1 订阅

运维一个可靠的系统 一个根本要就是能够优雅的处理过载的情况。

CPU资源的不足导致的负载上升是我们工作中最常见的,如果CPU资源不足以应对请求负载,一般来说所有的请求都会变慢,CPU负载过高会造成一系列的副作用,主要包括以下几项:

  • 正在处理的(in-flight) 的请求数量上升

  • 服务器逐渐将请求队列填满,意味着延迟上升,同时队列会用更多的内存

  • 线程卡住,无法处理请求

  • cpu死锁或者请求卡主

  • rpc服务调用超时

  • cpu的缓存效率下降

应对服务器过载几种常见的策略:

  • 服务降级
    返回精度降低的回复,或者省略回复中需要经过大量计算的数据;
    例如 :平时整个文档中进行搜索,在过载的情况下只搜索文档中的一小部分
  • 服务端拒绝请求
  • 客户端主动拒绝请求

一  资源利用率信号

在多数情况下,资源利用率仅仅是只当前cpu的消耗程度,在某些情况下也会考虑内存的使用情况。

当某个请求突然大批短时请求时,会导致负载的短时急剧上升。可以使用指数型衰变算法(exponential dacay)来平滑这个值。

go-zero案例:

go-zero种cpu的统计代码位于core/stat/internal中,通过获取linux系统的中/proc/stat提供的就是系统的CPU等的任务统计信息来计算cpu的使用率。
cpu统计代码会 没间隔250ms获取一次cpu的使用率,并且每一分钟打印一次cpu的使用率。


const (
	// 250ms and 0.95 as beta will count the average cpu load for past 5 seconds
	cpuRefreshInterval = time.Millisecond * 250
	allRefreshInterval = time.Minute
	// moving average beta hyperparameter
	beta = 0.95
)

func init() {
	go func() {
		cpuTicker := time.NewTicker(cpuRefreshInterval)
		defer cpuTicker.Stop()
		allTicker := time.NewTicker(allRefreshInterval)
		defer allTicker.Stop()

		for {
			select {
			case <-cpuTicker.C:
				threading.RunSafe(func() {
					curUsage := internal.RefreshCpu()
					prevUsage := atomic.LoadInt64(&cpuUsage)
					// cpu = cpuᵗ⁻¹ * beta + cpuᵗ * (1 - beta)
                    //指数衰变算法 
					usage := int64(float64(prevUsage)*beta + float64(curUsage)*(1-beta))
					atomic.StoreInt64(&cpuUsage, usage)
				})
			case <-allTicker.C:
				printUsage()
			}
		}
	}()
}

二 服务端过载保护


go-zero中内置的过载保护代码位于/core/load/adaptiveshedder.go

sholdDrop用来检测是否符合触发过载保护条件,代码入下

func (as *adaptiveShedder) shouldDrop() bool {
	if as.systemOverloaded() || as.stillHot() {
		if as.highThru() {
			flying := atomic.LoadInt64(&as.flying)
			as.avgFlyingLock.Lock()
			avgFlying := as.avgFlying
			as.avgFlyingLock.Unlock()
			msg := fmt.Sprintf(
				"dropreq, cpu: %d, maxPass: %d, minRt: %.2f, hot: %t, flying: %d, avgFlying: %.2f",
				stat.CpuUsage(), as.maxPass(), as.minRt(), as.stillHot(), flying, avgFlying)
			logx.Error(msg)
			stat.Report(msg)
			return true
		}
	}

	return false
}

as.systemOverloaded() 方法判断当前cpu是否达到阈值,默认90%。
as.stillHot() 判断是否在冷却期。
as.highThru()判断仍是高吞吐。
如果触发过载保护,会返回过载错误信息,并记录错误日志。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值