update the advanced circuit_breaker

This commit is contained in:
Edward 2020-05-22 17:57:41 +08:00
parent c8bd5eed55
commit 48a219b987
5 changed files with 35 additions and 28 deletions

View File

@ -3,7 +3,7 @@ package circuit
import "time" import "time"
//BreakConditionWatcher check state //BreakConditionWatcher check state
type BreakConditionWatcher func(counts counters) bool type BreakConditionWatcher func(cnter counters) bool
//StateChangedEventHandler set event handle //StateChangedEventHandler set event handle
type StateChangedEventHandler func(name string, from State, to State) type StateChangedEventHandler func(name string, from State, to State)
@ -60,8 +60,8 @@ func Expiry(expiry time.Time) Option {
} }
} }
//OnStateChanged set handle of ChangedHandle //WithStateChanged set handle of ChangedHandle
func OnStateChanged(handler StateChangedEventHandler) Option { func WithStateChanged(handler StateChangedEventHandler) Option {
return func(opts *Options) { return func(opts *Options) {
opts.OnStateChanged = handler opts.OnStateChanged = handler
} }

View File

@ -3,7 +3,7 @@
* @Author: Edward * @Author: Edward
* @Date: 2020-05-10 22:00:58 * @Date: 2020-05-10 22:00:58
* @Last Modified by: Edward * @Last Modified by: Edward
* @Last Modified time: 2020-05-22 16:44:57 * @Last Modified time: 2020-05-22 17:25:56
*/ */
package circuit package circuit
@ -36,15 +36,16 @@ const (
//////////////////////////////// ////////////////////////////////
//way 2 对象式断路器 //way 2 对象式断路器
// 高级模式 // 高级模式
// 支持多工作者模式
//////////////////////////////// ////////////////////////////////
//RequestBreaker for protection //RequestBreaker for protection
type RequestBreaker struct { type RequestBreaker struct {
options Options options Options
mutex sync.Mutex mutex sync.Mutex
state OperationState //断路器的当前状态 state State
generation uint64 generation uint64
counts ICounter cnter ICounter
} }
//NewRequestBreaker return a breaker //NewRequestBreaker return a breaker
@ -56,7 +57,7 @@ func NewRequestBreaker(opts ...Option) *RequestBreaker {
Interval: time.Second * 2, // interval to check status Interval: time.Second * 2, // interval to check status
Timeout: time.Second * 60, //default to 60 seconds Timeout: time.Second * 60, //default to 60 seconds
MaxRequests: 5, MaxRequests: 5,
WhenToBreak: func(counts counters) bool { return counts.ConsecutiveFailures > 2 }, WhenToBreak: func(cnter counters) bool { return cnter.ConsecutiveFailures > 2 },
OnStateChanged: func(name string, fromPre State, toCurrent State) {}, OnStateChanged: func(name string, fromPre State, toCurrent State) {},
} }
@ -67,7 +68,7 @@ func NewRequestBreaker(opts ...Option) *RequestBreaker {
return &RequestBreaker{ return &RequestBreaker{
options: defaultOptions, options: defaultOptions,
counts: &counters{}, cnter: &counters{},
generation: 0, generation: 0,
} }
} }
@ -79,14 +80,18 @@ func NewRequestBreaker(opts ...Option) *RequestBreaker {
func (rb *RequestBreaker) Do(work func() (interface{}, error)) (interface{}, error) { func (rb *RequestBreaker) Do(work func() (interface{}, error)) (interface{}, error) {
//before //before
fmt.Println("before do : request:", rb.counts.Total()) fmt.Println("before do : request:", rb.cnter.Total())
//handle status //handle status
if rb.state == StateOpen && rb.options.Expiry.Before(time.Now()) {
}
//do work from requested user //do work from requested user
result, err := work() result, err := work()
fmt.Println("after do : request:", rb.counts.Total()) fmt.Println("after do : request:", rb.cnter.Total())
return result, err return result, err
} }

View File

@ -3,7 +3,7 @@
* @Author: Edward * @Author: Edward
* @Date: 2020-05-11 10:55:28 * @Date: 2020-05-11 10:55:28
* @Last Modified by: Edward * @Last Modified by: Edward
* @Last Modified time: 2020-05-22 16:37:21 * @Last Modified time: 2020-05-22 17:21:06
*/ */
package circuit package circuit
@ -19,6 +19,16 @@ import (
var breaker *RequestBreaker var breaker *RequestBreaker
var onStateChangeEvent = func(name string, from, to State) {
fmt.Println("name:", name, "from:", from, "to", to)
}
var whenConditionOccurred = func(cnter counters) bool {
//失败率,可以由用户自己定义
failureRatio := float64(cnter.TotalFailures) / float64(cnter.Requests)
return cnter.Requests >= 3 && failureRatio >= 0.6
}
func TestObjectBreaker(t *testing.T) { func TestObjectBreaker(t *testing.T) {
jobToDo := func() (interface{}, error) { jobToDo := func() (interface{}, error) {
@ -34,13 +44,7 @@ func TestObjectBreaker(t *testing.T) {
return body, nil return body, nil
} }
whenCondition := func(counts counters) bool { breaker = NewRequestBreaker(Name("HTTP GET"), BreakIf(whenConditionOccurred), WithStateChanged(onStateChangeEvent))
//失败率,可以由用户自己定义
failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
return counts.Requests >= 3 && failureRatio >= 0.6
}
breaker = NewRequestBreaker(Name("HTTP GET"), BreakIf(whenCondition))
body, err := breaker.Do(jobToDo) body, err := breaker.Do(jobToDo)
if err != nil { if err != nil {

View File

@ -3,7 +3,7 @@
* @Author: Edward * @Author: Edward
* @Date: 2020-05-22 12:41:54 * @Date: 2020-05-22 12:41:54
* @Last Modified by: Edward * @Last Modified by: Edward
* @Last Modified time: 2020-05-22 16:47:37 * @Last Modified time: 2020-05-22 17:22:35
*/ */
package circuit package circuit
@ -40,7 +40,6 @@ type ICounter interface {
type counters struct { type counters struct {
Requests uint32 //连续的请求次数 Requests uint32 //连续的请求次数
lastState OperationState
lastActivity time.Time lastActivity time.Time
TotalFailures uint32 TotalFailures uint32
TotalSuccesses uint32 TotalSuccesses uint32
@ -59,7 +58,6 @@ func (c *counters) LastActivity() time.Time {
func (c *counters) Reset() { func (c *counters) Reset() {
ct := &counters{} ct := &counters{}
ct.lastActivity = c.lastActivity ct.lastActivity = c.lastActivity
ct.lastState = c.lastState
c = ct c = ct
} }
@ -74,7 +72,7 @@ func (c *counters) Count(statue OperationState) {
} }
c.Requests++ c.Requests++
c.lastActivity = time.Now() //更新活动时间 c.lastActivity = time.Now() //更新活动时间
c.lastState = statue // c.lastOpResult = statue
//handle status change //handle status change
} }

View File

@ -3,7 +3,7 @@
* @Author: Edward * @Author: Edward
* @Date: 2020-05-22 12:42:34 * @Date: 2020-05-22 12:42:34
* @Last Modified by: Edward * @Last Modified by: Edward
* @Last Modified time: 2020-05-22 16:48:56 * @Last Modified time: 2020-05-22 17:21:40
*/ */
package circuit package circuit
@ -31,7 +31,7 @@ const (
) )
type simpleCounter struct { type simpleCounter struct {
lastState OperationState lastOpResult OperationState
lastActivity time.Time lastActivity time.Time
ConsecutiveSuccesses uint32 ConsecutiveSuccesses uint32
ConsecutiveFailures uint32 ConsecutiveFailures uint32
@ -44,21 +44,21 @@ func (c *simpleCounter) LastActivity() time.Time {
func (c *simpleCounter) Reset() { func (c *simpleCounter) Reset() {
ct := &simpleCounter{} ct := &simpleCounter{}
ct.lastActivity = c.lastActivity ct.lastActivity = c.lastActivity
ct.lastState = UnknownState ct.lastOpResult = UnknownState
c = ct c = ct
} }
//Count the failure and success //Count the failure and success
func (c *simpleCounter) Count(statue OperationState) { func (c *simpleCounter) Count(lastState OperationState) {
switch statue { switch lastState {
case FailureState: case FailureState:
c.ConsecutiveFailures++ c.ConsecutiveFailures++
case SuccessState: case SuccessState:
c.ConsecutiveSuccesses++ c.ConsecutiveSuccesses++
} }
c.lastActivity = time.Now() //更新活动时间 c.lastActivity = time.Now() //更新活动时间
c.lastState = statue c.lastOpResult = lastState
//handle status change //handle status change
} }