在某些场景下,会引入熔断机制来保证服务的稳定性。本文介绍用Go语言自己实现断路器需要哪些操作。什么是断路器?熔断是指下游发生错误时,上游主动关闭或限制对下游的请求。原理一般熔断器分为三个时期:CLOSED、OPEN、HALFOPEN。RPC正常时为CLOSED;当RPC错误增加时,熔断器将被触发并进入OPEN;OPEN后经过一定的冷却时间后,熔断器会变为HALFOPEN;HALFOPEN会对下游进行一些战略访问,然后根据结果决定是改为CLOSED还是OPEN;总的来说,三种状态的转换大致如下:去实现https://github.com/rubyist/circuitbreakerIsAllowed是否允许请求,根据当前状态判断CLOSEallowOPEN在CoolingTimeout冷却时间内,冷却时间不允许,状态变为HALFOPEN,在DetectTimeout检测时间内允许访问HALFOPEN,否则不允许访问atomic.StoreInt32((*int32)(&b.state),int32(HALFOPEN))trip判断是否熔断限流达到(可自定义)typeTripFuncfunc(Metricser)boolThresholdTripFunc错误阈值ConsecutiveTripFunc连续错误超过阈值RateTripFunc根据最小访问次数和错误率判断Metricser访问统计,包括成功次数,失败次数,超时次数,错误rate,样本数,连续错误数typeMetricserinterface{Fail()//recordsafailureSucceed()//recordsasuccessTimeout()//recordsatimeoutFailures()int64//返回失败次数Successes()int64//返回成功次数Timeouts()int64//返回超时次数ConseErrors()int64//返回最近的连续错误ErrorRate()float64//rate=(timeouts+failures)/(timeouts+failures+successes)Samples()int64//(timeouts+failures+successes)Counts()(successes,failures,timeoutsint64)Reset()}windowimplementationclasstypewindowstruct{sync.RWMutexoldestint32//oldestbucketindexlatestint32//latestbucketindexbuckets[]bucket//bucketsthiswindowholdsbucketTimetime.Duration//timeeachbucketholdsbucketNumsint32//thenumbeofbucketsinWindowint32//thenumberofbucketsinthewindowallSuccessint64allFailureint64allTimeoutint64conseErrint64}typebucketstruct{failureint64successint64timeoutint64}用环形队列实现动态统计把一个连续的时间切成多个小份,每一个bucket保存BucketTime的统计数据,BucketTime*BucketNums是Statisticaltimeinterval.每一个BucketTime,都会有一个bucketexpired())atomic.AddInt64(&w.allFailure,-oldBucket.Failures())atomic.AddInt64(&w.allTimeout,-oldBucket.Timeouts())w.oldest++ifw.oldest>=w.bucketNums{w.oldest=0}}else{w.inWindow++}w.latest++ifw.latest>=w.bucketNums{w.latest=0}(&w.buckets[w.latest]).Reset()PanelMetricser容器PanelStateChangeHandlerfuseeventtypePanelStateChangeHandlerfunc(keystring,oldState,newStateState,mMetricser)缺陷所有breaker共享同一个BucketTime,统计周期不支持更新冷却时间不支持动态更新
