mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-28 22:46:03 +03:00
update the advanced circuit_breaker
This commit is contained in:
parent
c8bd5eed55
commit
48a219b987
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user