Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 39 additions & 40 deletions api/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,44 +21,43 @@
//
// Here is the example code to use Sentinel:
//
// import sentinel "github.com/alibaba/sentinel-golang/api"
//
// err := sentinel.InitDefault()
// if err != nil {
// log.Fatal(err)
// }
//
// //Load sentinel rules
// _, err = flow.LoadRules([]*flow.Rule{
// {
// Resource: "some-test",
// MetricType: flow.QPS,
// Threshold: 10,
// ControlBehavior: flow.Reject,
// },
// })
// if err != nil {
// log.Fatalf("Unexpected error: %+v", err)
// return
// }
// ch := make(chan struct{})
// for i := 0; i < 10; i++ {
// go func() {
// for {
// e, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound))
// if b != nil {
// // Blocked. We could get the block reason from the BlockError.
// time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
// } else {
// // Passed, wrap the logic here.
// fmt.Println(util.CurrentTimeMillis(), "passed")
// time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
// // Be sure the entry is exited finally.
// e.Exit()
// }
// }
// }()
// }
// <-ch
//
// import sentinel "github.com/alibaba/sentinel-golang/api"
//
// err := sentinel.InitDefault()
// if err != nil {
// log.Fatal(err)
// }
//
// //Load sentinel rules
// _, err = flow.LoadRules([]*flow.Rule{
// {
// Resource: "some-test",
// MetricType: flow.QPS,
// Threshold: 10,
// ControlBehavior: flow.Reject,
// },
// })
// if err != nil {
// log.Fatalf("Unexpected error: %+v", err)
// return
// }
// ch := make(chan struct{})
// for i := 0; i < 10; i++ {
// go func() {
// for {
// e, b := sentinel.Entry("some-test", sentinel.WithTrafficType(base.Inbound))
// if b != nil {
// // Blocked. We could get the block reason from the BlockError.
// time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
// } else {
// // Passed, wrap the logic here.
// fmt.Println(util.CurrentTimeMillis(), "passed")
// time.Sleep(time.Duration(rand.Uint64()%10) * time.Millisecond)
// // Be sure the entry is exited finally.
// e.Exit()
// }
// }
// }()
// }
// <-ch
package api
7 changes: 4 additions & 3 deletions api/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ import (
)

// Initialization func initialize the Sentinel's runtime environment, including:
// 1. override global config, from manually config or yaml file or env variable
// 2. override global logger
// 3. initiate core component async task, including: metric log, system statistic...
// 1. override global config, from manually config or yaml file or env variable
// 2. override global logger
// 3. initiate core component async task, including: metric log, system statistic...
//
// InitDefault initializes Sentinel using the configuration from system
// environment and the default value.
func InitDefault() error {
Expand Down
33 changes: 16 additions & 17 deletions core/circuitbreaker/circuit_breaker.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,19 @@ import (
"github.com/pkg/errors"
)

// Circuit Breaker State Machine:
//
// Circuit Breaker State Machine:
//
// switch to open based on rule
// +-----------------------------------------------------------------------+
// | |
// | v
// +----------------+ +----------------+ Probe +----------------+
// | | | |<----------------| |
// | | Probe succeed | | | |
// | Closed |<------------------| HalfOpen | | Open |
// | | | | Probe failed | |
// | | | +---------------->| |
// +----------------+ +----------------+ +----------------+
// switch to open based on rule
// +-----------------------------------------------------------------------+
// | |
// | v
// +----------------+ +----------------+ Probe +----------------+
// | | | |<----------------| |
// | | Probe succeed | | | |
// | Closed |<------------------| HalfOpen | | Open |
// | | | | Probe failed | |
// | | | +---------------->| |
// +----------------+ +----------------+ +----------------+
type State int32

const (
Expand Down Expand Up @@ -126,7 +125,7 @@ type CircuitBreaker interface {
OnRequestComplete(rtt uint64, err error)
}

//================================= circuitBreakerBase ====================================
// ================================= circuitBreakerBase ====================================
// circuitBreakerBase encompasses the common fields of circuit breaker.
type circuitBreakerBase struct {
rule *Rule
Expand Down Expand Up @@ -245,7 +244,7 @@ func (b *circuitBreakerBase) fromHalfOpenToClosed() bool {
return false
}

//================================= slowRtCircuitBreaker ====================================
// ================================= slowRtCircuitBreaker ====================================
type slowRtCircuitBreaker struct {
circuitBreakerBase
stat *slowRequestLeapArray
Expand Down Expand Up @@ -437,7 +436,7 @@ func (s *slowRequestLeapArray) allCounter() []*slowRequestCounter {
return ret
}

//================================= errorRatioCircuitBreaker ====================================
// ================================= errorRatioCircuitBreaker ====================================
type errorRatioCircuitBreaker struct {
circuitBreakerBase
minRequestAmount uint64
Expand Down Expand Up @@ -622,7 +621,7 @@ func (s *errorCounterLeapArray) allCounter() []*errorCounter {
return ret
}

//================================= errorCountCircuitBreaker ====================================
// ================================= errorCountCircuitBreaker ====================================
type errorCountCircuitBreaker struct {
circuitBreakerBase
minRequestAmount uint64
Expand Down
177 changes: 88 additions & 89 deletions core/circuitbreaker/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// Sentinel circuit breaker module supports three strategies:
//
// 1. SlowRequestRatio: the ratio of slow response time entry(entry's response time is great than max slow response time) exceeds the threshold. The following entry to resource will be broken.
// In SlowRequestRatio strategy, user must set max response time.
// In SlowRequestRatio strategy, user must set max response time.
// 2. ErrorRatio: the ratio of error entry exceeds the threshold. The following entry to resource will be broken.
// 3. ErrorCount: the number of error entry exceeds the threshold. The following entry to resource will be broken.
//
Expand All @@ -32,97 +32,96 @@
//
// Sentinel circuit breaker provides the listener to observe events of state changes.
//
// type StateChangeListener interface {
// OnTransformToClosed(prev State, rule Rule)
// type StateChangeListener interface {
// OnTransformToClosed(prev State, rule Rule)
//
// OnTransformToOpen(prev State, rule Rule, snapshot interface{})
// OnTransformToOpen(prev State, rule Rule, snapshot interface{})
//
// OnTransformToHalfOpen(prev State, rule Rule)
// }
// OnTransformToHalfOpen(prev State, rule Rule)
// }
//
// Here is the example code to use circuit breaker:
//
// type stateChangeTestListener struct {}
//
// func (s *stateChangeTestListener) OnTransformToClosed(prev circuitbreaker.State, rule circuitbreaker.Rule) {
// fmt.Printf("rule.steategy: %+v, From %s to Closed, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
// }
//
// func (s *stateChangeTestListener) OnTransformToOpen(prev circuitbreaker.State, rule circuitbreaker.Rule, snapshot interface{}) {
// fmt.Printf("rule.steategy: %+v, From %s to Open, snapshot: %.2f, time: %d\n", rule.Strategy, prev.String(), snapshot, util.CurrentTimeMillis())
// }
//
// func (s *stateChangeTestListener) OnTransformToHalfOpen(prev circuitbreaker.State, rule circuitbreaker.Rule) {
// fmt.Printf("rule.steategy: %+v, From %s to Half-Open, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
// }
//
// func main() {
// err := sentinel.InitDefault()
// if err != nil {
// log.Fatal(err)
// }
// ch := make(chan struct{})
// // Register a state change listener so that we could observer the state change of the internal circuit breaker.
// circuitbreaker.RegisterStateChangeListeners(&stateChangeTestListener{})
//
// _, err = circuitbreaker.LoadRules([]*circuitbreaker.Rule{
// // Statistic time span=10s, recoveryTimeout=3s, slowRtUpperBound=50ms, maxSlowRequestRatio=50%
// {
// Resource: "abc",
// Strategy: circuitbreaker.SlowRequestRatio,
// RetryTimeoutMs: 3000,
// MinRequestAmount: 10,
// StatIntervalMs: 10000,
// MaxAllowedRtMs: 50,
// Threshold: 0.5,
// },
// // Statistic time span=10s, recoveryTimeout=3s, maxErrorRatio=50%
// {
// Resource: "abc",
// Strategy: circuitbreaker.ErrorRatio,
// RetryTimeoutMs: 3000,
// MinRequestAmount: 10,
// StatIntervalMs: 10000,
// Threshold: 0.5,
// },
// })
// if err != nil {
// log.Fatal(err)
// }
//
// fmt.Println("Sentinel Go circuit breaking demo is running. You may see the pass/block metric in the metric log.")
// go func() {
// for {
// e, b := sentinel.Entry("abc")
// if b != nil {
// //fmt.Println("g1blocked")
// time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)
// } else {
// if rand.Uint64()%20 > 9 {
// // Record current invocation as error.
// sentinel.TraceError(e, errors.New("biz error"))
// }
// //fmt.Println("g1passed")
// time.Sleep(time.Duration(rand.Uint64()%80+10) * time.Millisecond)
// e.Exit()
// }
// }
// }()
//
// go func() {
// for {
// e, b := sentinel.Entry("abc")
// if b != nil {
// //fmt.Println("g2blocked")
// time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)
// } else {
// //fmt.Println("g2passed")
// time.Sleep(time.Duration(rand.Uint64()%80) * time.Millisecond)
// e.Exit()
// }
// }
// }()
// <-ch
// }
//
// type stateChangeTestListener struct {}
//
// func (s *stateChangeTestListener) OnTransformToClosed(prev circuitbreaker.State, rule circuitbreaker.Rule) {
// fmt.Printf("rule.steategy: %+v, From %s to Closed, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
// }
//
// func (s *stateChangeTestListener) OnTransformToOpen(prev circuitbreaker.State, rule circuitbreaker.Rule, snapshot interface{}) {
// fmt.Printf("rule.steategy: %+v, From %s to Open, snapshot: %.2f, time: %d\n", rule.Strategy, prev.String(), snapshot, util.CurrentTimeMillis())
// }
//
// func (s *stateChangeTestListener) OnTransformToHalfOpen(prev circuitbreaker.State, rule circuitbreaker.Rule) {
// fmt.Printf("rule.steategy: %+v, From %s to Half-Open, time: %d\n", rule.Strategy, prev.String(), util.CurrentTimeMillis())
// }
//
// func main() {
// err := sentinel.InitDefault()
// if err != nil {
// log.Fatal(err)
// }
// ch := make(chan struct{})
// // Register a state change listener so that we could observer the state change of the internal circuit breaker.
// circuitbreaker.RegisterStateChangeListeners(&stateChangeTestListener{})
//
// _, err = circuitbreaker.LoadRules([]*circuitbreaker.Rule{
// // Statistic time span=10s, recoveryTimeout=3s, slowRtUpperBound=50ms, maxSlowRequestRatio=50%
// {
// Resource: "abc",
// Strategy: circuitbreaker.SlowRequestRatio,
// RetryTimeoutMs: 3000,
// MinRequestAmount: 10,
// StatIntervalMs: 10000,
// MaxAllowedRtMs: 50,
// Threshold: 0.5,
// },
// // Statistic time span=10s, recoveryTimeout=3s, maxErrorRatio=50%
// {
// Resource: "abc",
// Strategy: circuitbreaker.ErrorRatio,
// RetryTimeoutMs: 3000,
// MinRequestAmount: 10,
// StatIntervalMs: 10000,
// Threshold: 0.5,
// },
// })
// if err != nil {
// log.Fatal(err)
// }
//
// fmt.Println("Sentinel Go circuit breaking demo is running. You may see the pass/block metric in the metric log.")
// go func() {
// for {
// e, b := sentinel.Entry("abc")
// if b != nil {
// //fmt.Println("g1blocked")
// time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)
// } else {
// if rand.Uint64()%20 > 9 {
// // Record current invocation as error.
// sentinel.TraceError(e, errors.New("biz error"))
// }
// //fmt.Println("g1passed")
// time.Sleep(time.Duration(rand.Uint64()%80+10) * time.Millisecond)
// e.Exit()
// }
// }
// }()
//
// go func() {
// for {
// e, b := sentinel.Entry("abc")
// if b != nil {
// //fmt.Println("g2blocked")
// time.Sleep(time.Duration(rand.Uint64()%20) * time.Millisecond)
// } else {
// //fmt.Println("g2passed")
// time.Sleep(time.Duration(rand.Uint64()%80) * time.Millisecond)
// e.Exit()
// }
// }
// }()
// <-ch
// }
package circuitbreaker
6 changes: 4 additions & 2 deletions core/circuitbreaker/rule_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ func init() {
// GetRulesOfResource returns specific resource's rules based on copy.
// It doesn't take effect for circuit breaker module if user changes the rule.
// GetRulesOfResource need to compete circuit breaker module's global lock and the high performance losses of copy,
// reduce or do not call GetRulesOfResource frequently if possible
//
// reduce or do not call GetRulesOfResource frequently if possible
func GetRulesOfResource(resource string) []Rule {
updateMux.RLock()
resRules, ok := breakerRules[resource]
Expand All @@ -106,7 +107,8 @@ func GetRulesOfResource(resource string) []Rule {
// GetRules returns all the rules based on copy.
// It doesn't take effect for circuit breaker module if user changes the rule.
// GetRules need to compete circuit breaker module's global lock and the high performance losses of copy,
// reduce or do not call GetRules if possible
//
// reduce or do not call GetRules if possible
func GetRules() []Rule {
updateMux.RLock()
rules := rulesFrom(breakerRules)
Expand Down
1 change: 0 additions & 1 deletion core/flow/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@
//
// 1. The function both SetTrafficShapingGenerator and RemoveTrafficShapingGenerator is not thread safe.
// 2. Users can not override the Sentinel supported TrafficShapingController.
//
package flow
1 change: 1 addition & 0 deletions core/flow/tc_adaptive.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
// If the watermark is less than Rule.MemLowWaterMarkBytes, the threshold is Rule.LowMemUsageThreshold.
// If the watermark is greater than Rule.MemHighWaterMarkBytes, the threshold is Rule.HighMemUsageThreshold.
// Otherwise, the threshold is ((watermark - MemLowWaterMarkBytes)/(MemHighWaterMarkBytes - MemLowWaterMarkBytes)) *
//
// (HighMemUsageThreshold - LowMemUsageThreshold) + LowMemUsageThreshold.
type MemoryAdaptiveTrafficShapingCalculator struct {
owner *TrafficShapingController
Expand Down
Loading