Skip to content

Commit 2c544a8

Browse files
authored
Polish code of circuit breaker module (#152)
* Polish code of circuit breaker module Signed-off-by: Eric Zhao <[email protected]>
1 parent 112f169 commit 2c544a8

File tree

6 files changed

+99
-89
lines changed

6 files changed

+99
-89
lines changed

core/circuitbreaker/circuit_breaker.go

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ func (s *State) get() State {
4949
statePtr := (*int32)(unsafe.Pointer(s))
5050
return State(atomic.LoadInt32(statePtr))
5151
}
52+
5253
func (s *State) set(update State) {
5354
statePtr := (*int32)(unsafe.Pointer(s))
5455
newState := int32(update)
5556
atomic.StoreInt32(statePtr, newState)
5657
}
58+
5759
func (s *State) casState(expect State, update State) bool {
5860
statePtr := (*int32)(unsafe.Pointer(s))
5961
oldState := int32(expect)
@@ -62,24 +64,29 @@ func (s *State) casState(expect State, update State) bool {
6264
}
6365

6466
type StateChangeListener interface {
65-
OnChangeToClosed(prev State, rule Rule)
67+
// OnTransformToClosed is triggered when circuit breaker state transformed to Closed.
68+
OnTransformToClosed(prev State, rule Rule)
6669

67-
OnChangeToOpen(prev State, rule Rule, snapshot interface{})
70+
// OnTransformToOpen is triggered when circuit breaker state transformed to Open.
71+
// The "snapshot" indicates the triggered value when the transformation occurs.
72+
OnTransformToOpen(prev State, rule Rule, snapshot interface{})
6873

69-
OnChangeToHalfOpen(prev State, rule Rule)
74+
// OnTransformToHalfOpen is triggered when circuit breaker state transformed to HalfOpen.
75+
OnTransformToHalfOpen(prev State, rule Rule)
7076
}
7177

7278
type CircuitBreaker interface {
79+
// BoundRule returns the associated circuit breaking rule.
7380
BoundRule() Rule
74-
81+
// BoundStat returns the associated statistic data structure.
7582
BoundStat() interface{}
76-
83+
// TryPass acquires permission of an invocation only if it is available at the time of invocation.
7784
TryPass(ctx *base.EntryContext) bool
78-
85+
// CurrentState returns current state of the circuit breaker.
7986
CurrentState() State
80-
// HandleCompleted handle the entry completed, Will not call HandleCompleted if request is blocked.
81-
// rt: the response time this entry cost.
82-
HandleCompleted(rt uint64, err error)
87+
// OnRequestComplete record a completed request with the given response time as well as error (if present),
88+
// and handle state transformation of the circuit breaker.
89+
OnRequestComplete(rtt uint64, err error)
8390
}
8491

8592
//================================= circuitBreakerBase ====================================
@@ -106,54 +113,50 @@ func (b *circuitBreakerBase) updateNextRetryTimestamp() {
106113
atomic.StoreUint64(&b.nextRetryTimestamp, util.CurrentTimeMillis()+uint64(b.retryTimeoutMs))
107114
}
108115

109-
// fromClosedToOpen update circuit breaker status machine from closed to open
110-
// Used for opening circuit breaker from closed when checking circuit breaker
111-
// return true if succeed to update
116+
// fromClosedToOpen updates circuit breaker state machine from closed to open.
117+
// Return true only if current goroutine successfully accomplished the transformation.
112118
func (b *circuitBreakerBase) fromClosedToOpen(snapshot interface{}) bool {
113119
if b.status.casState(Closed, Open) {
114120
b.updateNextRetryTimestamp()
115-
for _, listener := range statusSwitchListeners {
116-
listener.OnChangeToOpen(Closed, b.rule, snapshot)
121+
for _, listener := range stateChangeListeners {
122+
listener.OnTransformToOpen(Closed, b.rule, snapshot)
117123
}
118124
return true
119125
}
120126
return false
121127
}
122128

123-
// fromOpenToHalfOpen update circuit breaker status machine from open to half-open
124-
// Used for probing
125-
// return true if succeed to update
129+
// fromOpenToHalfOpen updates circuit breaker state machine from open to half-open.
130+
// Return true only if current goroutine successfully accomplished the transformation.
126131
func (b *circuitBreakerBase) fromOpenToHalfOpen() bool {
127132
if b.status.casState(Open, HalfOpen) {
128-
for _, listener := range statusSwitchListeners {
129-
listener.OnChangeToHalfOpen(Open, b.rule)
133+
for _, listener := range stateChangeListeners {
134+
listener.OnTransformToHalfOpen(Open, b.rule)
130135
}
131136
return true
132137
}
133138
return false
134139
}
135140

136-
// fromHalfOpenToOpen update circuit breaker status machine from half-open to open
137-
// Used for failing to probe
138-
// return true if succeed to update
141+
// fromHalfOpenToOpen updates circuit breaker state machine from half-open to open.
142+
// Return true only if current goroutine successfully accomplished the transformation.
139143
func (b *circuitBreakerBase) fromHalfOpenToOpen(snapshot interface{}) bool {
140144
if b.status.casState(HalfOpen, Open) {
141145
b.updateNextRetryTimestamp()
142-
for _, listener := range statusSwitchListeners {
143-
listener.OnChangeToOpen(HalfOpen, b.rule, snapshot)
146+
for _, listener := range stateChangeListeners {
147+
listener.OnTransformToOpen(HalfOpen, b.rule, snapshot)
144148
}
145149
return true
146150
}
147151
return false
148152
}
149153

150-
// fromHalfOpenToOpen update circuit breaker status machine from half-open to closed
151-
// Used for succeeding to probe
152-
// return true if succeed to update
154+
// fromHalfOpenToOpen updates circuit breaker state machine from half-open to closed
155+
// Return true only if current goroutine successfully accomplished the transformation.
153156
func (b *circuitBreakerBase) fromHalfOpenToClosed() bool {
154157
if b.status.casState(HalfOpen, Closed) {
155-
for _, listener := range statusSwitchListeners {
156-
listener.OnChangeToClosed(HalfOpen, b.rule)
158+
for _, listener := range stateChangeListeners {
159+
listener.OnTransformToClosed(HalfOpen, b.rule)
157160
}
158161
return true
159162
}
@@ -198,7 +201,7 @@ func (b *slowRtCircuitBreaker) BoundStat() interface{} {
198201
return b.stat
199202
}
200203

201-
// TryPass check circuit breaker based on status machine of circuit breaker.
204+
// TryPass check circuit breaker based on state machine of circuit breaker.
202205
func (b *slowRtCircuitBreaker) TryPass(_ *base.EntryContext) bool {
203206
curStatus := b.CurrentState()
204207
if curStatus == Closed {
@@ -212,7 +215,7 @@ func (b *slowRtCircuitBreaker) TryPass(_ *base.EntryContext) bool {
212215
return false
213216
}
214217

215-
func (b *slowRtCircuitBreaker) HandleCompleted(rt uint64, err error) {
218+
func (b *slowRtCircuitBreaker) OnRequestComplete(rt uint64, err error) {
216219
// add slow and add total
217220
metricStat := b.stat
218221
counter := metricStat.currentCounter()
@@ -393,7 +396,7 @@ func (b *errorRatioCircuitBreaker) TryPass(_ *base.EntryContext) bool {
393396
return false
394397
}
395398

396-
func (b *errorRatioCircuitBreaker) HandleCompleted(rt uint64, err error) {
399+
func (b *errorRatioCircuitBreaker) OnRequestComplete(rt uint64, err error) {
397400
metricStat := b.stat
398401
counter := metricStat.currentCounter()
399402
if err != nil {
@@ -570,7 +573,7 @@ func (b *errorCountCircuitBreaker) TryPass(_ *base.EntryContext) bool {
570573
return false
571574
}
572575

573-
func (b *errorCountCircuitBreaker) HandleCompleted(rt uint64, err error) {
576+
func (b *errorCountCircuitBreaker) OnRequestComplete(rt uint64, err error) {
574577
metricStat := b.stat
575578
counter := metricStat.currentCounter()
576579
if err != nil {

core/circuitbreaker/circuit_breaker_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import (
44
"testing"
55

66
"github.com/alibaba/sentinel-golang/core/base"
7-
8-
"github.com/stretchr/testify/mock"
9-
107
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/mock"
119
)
1210

1311
type CircuitBreakerMock struct {
@@ -19,6 +17,11 @@ func (m *CircuitBreakerMock) BoundRule() Rule {
1917
return args.Get(0).(Rule)
2018
}
2119

20+
func (m *CircuitBreakerMock) BoundStat() interface{} {
21+
args := m.Called()
22+
return args.Get(0)
23+
}
24+
2225
func (m *CircuitBreakerMock) TryPass(ctx *base.EntryContext) bool {
2326
args := m.Called(ctx)
2427
return args.Bool(0)
@@ -29,9 +32,7 @@ func (m *CircuitBreakerMock) CurrentState() State {
2932
return args.Get(0).(State)
3033
}
3134

32-
// HandleCompleted handle the entry completed
33-
// rt: the response time this entry cost.
34-
func (m *CircuitBreakerMock) HandleCompleted(rt uint64, err error) {
35+
func (m *CircuitBreakerMock) OnRequestComplete(rt uint64, err error) {
3536
m.Called(rt, err)
3637
return
3738
}

core/circuitbreaker/rule.go

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,26 @@ package circuitbreaker
33
import (
44
"fmt"
55

6-
"go.uber.org/multierr"
7-
86
"github.com/alibaba/sentinel-golang/core/base"
97
"github.com/alibaba/sentinel-golang/util"
108
"github.com/pkg/errors"
9+
"go.uber.org/multierr"
1110
)
1211

13-
// The strategy of circuit breaker
14-
// Each strategy represent one rule type
12+
// The strategy of circuit breaker.
13+
// Each strategy represents one rule type.
1514
type Strategy int8
1615

1716
const (
18-
SlowRt Strategy = iota
17+
SlowRequestRatio Strategy = iota
1918
ErrorRatio
2019
ErrorCount
2120
)
2221

2322
func (s Strategy) String() string {
2423
switch s {
25-
case SlowRt:
26-
return "SlowRt"
24+
case SlowRequestRatio:
25+
return "SlowRequestRatio"
2726
case ErrorRatio:
2827
return "ErrorRatio"
2928
case ErrorCount:
@@ -33,32 +32,36 @@ func (s Strategy) String() string {
3332
}
3433
}
3534

36-
// The base interface of circuit breaker rule
35+
// Rule represents the base interface of the circuit breaker rule.
3736
type Rule interface {
3837
base.SentinelRule
39-
// return the strategy type
38+
// BreakerStrategy returns the strategy.
4039
BreakerStrategy() Strategy
41-
// check whether the rule is valid and could be converted to corresponding circuit breaker
40+
// IsApplicable checks whether the rule is valid and could be converted to a corresponding circuit breaker.
4241
IsApplicable() error
43-
// return circuit breaker stat interval
42+
// BreakerStatIntervalMs returns the statistic interval of circuit breaker (in milliseconds).
4443
BreakerStatIntervalMs() uint32
45-
// check whether is consistent with new rule
44+
// IsEqualsTo checks whether current rule is consistent with the given rule.
4645
IsEqualsTo(r Rule) bool
47-
// check whether the statistic of old circuit breaker is reuseable for new circuit breaker
46+
// IsStatReusable checks whether current rule is "statistically" equal to the given rule.
4847
IsStatReusable(r Rule) bool
4948
}
5049

51-
// The common fields of circuit breaker rule
50+
// RuleBase encompasses common fields of circuit breaking rule.
5251
type RuleBase struct {
5352
// unique id
5453
Id string
5554
// resource name
5655
Resource string
5756
Strategy Strategy
58-
// auto recover timeout in ms, all requests would be broken before auto recover
59-
RetryTimeoutMs uint32
57+
// RetryTimeoutMs represents recovery timeout (in seconds) before the circuit breaker opens.
58+
// During the open period, no requests are permitted until the timeout has elapsed.
59+
// After that, the circuit breaker will transform to half-open state for trying a few "trial" requests.
60+
RetryTimeoutMs uint32
61+
// MinRequestAmount represents the minimum number of requests (in an active statistic time span)
62+
// that can trigger circuit breaking.
6063
MinRequestAmount uint64
61-
64+
// StatIntervalMs represents statistic time interval of the internal circuit breaker (in ms).
6265
StatIntervalMs uint32
6366
}
6467

@@ -92,11 +95,13 @@ func (b *RuleBase) ResourceName() string {
9295
return b.Resource
9396
}
9497

95-
// SlowRt circuit breaker rule
98+
// SlowRequestRatio circuit breaker rule
9699
type slowRtRule struct {
97100
RuleBase
98-
// max allowed rt in ms
99-
MaxAllowedRt uint64
101+
// MaxAllowedRt indicates that any invocation whose response time exceeds this value
102+
// will be recorded as a slow request.
103+
MaxAllowedRt uint64
104+
// MaxSlowRequestRatio represents the threshold of slow request ratio.
100105
MaxSlowRequestRatio float64
101106
}
102107

@@ -105,7 +110,7 @@ func NewSlowRtRule(resource string, intervalMs uint32, retryTimeoutMs uint32, ma
105110
RuleBase: RuleBase{
106111
Id: util.NewUuid(),
107112
Resource: resource,
108-
Strategy: SlowRt,
113+
Strategy: SlowRequestRatio,
109114
RetryTimeoutMs: retryTimeoutMs,
110115
MinRequestAmount: minRequestAmount,
111116
StatIntervalMs: intervalMs,

0 commit comments

Comments
 (0)