diff --git a/pkg/net/netutil/breaker/sre_breaker.go b/pkg/net/netutil/breaker/sre_breaker.go index ef4c32856..4627369ff 100644 --- a/pkg/net/netutil/breaker/sre_breaker.go +++ b/pkg/net/netutil/breaker/sre_breaker.go @@ -12,12 +12,6 @@ import ( "github.com/bilibili/kratos/pkg/stat/metric" ) -var ( - // rand.New(...) returns a non thread safe object - random = rand.New(rand.NewSource(time.Now().UnixNano())) - lock sync.Mutex -) - // sreBreaker is a sre CircuitBreaker pattern. type sreBreaker struct { stat metric.RollingCounter @@ -26,6 +20,10 @@ type sreBreaker struct { request int64 state int32 + + random *rand.Rand + // rand.New(...) returns a non thread safe object + randLock sync.Mutex } func newSRE(c *Config) Breaker { @@ -40,6 +38,7 @@ func newSRE(c *Config) Breaker { request: c.Request, k: c.K, state: StateClosed, + random: rand.New(rand.NewSource(time.Now().UnixNano())), } } @@ -74,7 +73,7 @@ func (b *sreBreaker) Allow() error { atomic.CompareAndSwapInt32(&b.state, StateClosed, StateOpen) } dr := math.Max(0, (float64(total)-k)/float64(total+1)) - drop := trueOnProba(dr) + drop := b.trueOnProba(dr) if log.V(5) { log.Info("breaker: drop ratio: %f, drop: %t", dr, drop) } @@ -94,9 +93,9 @@ func (b *sreBreaker) MarkFailed() { b.stat.Add(0) } -func trueOnProba(proba float64) (truth bool) { - lock.Lock() - truth = random.Float64() < proba - lock.Unlock() +func (b *sreBreaker) trueOnProba(proba float64) (truth bool) { + b.randLock.Lock() + truth = b.random.Float64() < proba + b.randLock.Unlock() return }