mirror of
https://github.com/crazybber/go-pattern-examples.git
synced 2024-11-25 21:26:03 +03:00
add an options
This commit is contained in:
parent
782b982ae1
commit
40a268bc3d
42
gomore/06_circuit_breaker/breaker_options.go
Normal file
42
gomore/06_circuit_breaker/breaker_options.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package circuit
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
//Options for breaker
|
||||||
|
type Options struct {
|
||||||
|
Name string
|
||||||
|
Expiry time.Time
|
||||||
|
Interval time.Duration
|
||||||
|
Timeout time.Duration
|
||||||
|
MaxRequests uint32
|
||||||
|
ReadyToTrip StateCheckerHandler
|
||||||
|
OnStateChanged StateChangedEventHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetName of breaker
|
||||||
|
func SetName(name string) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetExpiry of breaker
|
||||||
|
func SetExpiry(expiry time.Time) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.Expiry = expiry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetStateChangedHandle set handle of ChangedHandle
|
||||||
|
func SetStateChangedHandle(handler StateChangedEventHandler) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.OnStateChanged = handler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetReadyToTrip check traffic state ,to see if request can go
|
||||||
|
func SetReadyToTrip(readyToGo StateCheckerHandler) Option {
|
||||||
|
return func(opts *Options) {
|
||||||
|
opts.ReadyToTrip = readyToGo
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,25 @@
|
|||||||
package circuit
|
package circuit
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @Description: https://github.com/crazybber
|
||||||
|
* @Author: Edward
|
||||||
|
* @Date: 2020-05-10 22:00:58
|
||||||
|
* @Last Modified by: Edward
|
||||||
|
* @Last Modified time: 2020-05-10 22:02:18
|
||||||
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
///使用HTTP请求的例子
|
||||||
|
//每个搜索引擎时时刻刻都会遇到超大规模的请求的流量.
|
||||||
|
//这里演示一个复杂一点的例子,同时使用Option 模式
|
||||||
|
|
||||||
//ErrServiceUnavailable for error
|
//ErrServiceUnavailable for error
|
||||||
var (
|
var (
|
||||||
ErrTooManyRequests = errors.New("too many requests")
|
ErrTooManyRequests = errors.New("too many requests")
|
||||||
@ -13,6 +27,29 @@ var (
|
|||||||
FailureThreshold = 10
|
FailureThreshold = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//StateCheckerHandler check state
|
||||||
|
type StateCheckerHandler func(counts counters) bool
|
||||||
|
|
||||||
|
//StateChangedEventHandler set event handle
|
||||||
|
type StateChangedEventHandler func(name string, from State, to State)
|
||||||
|
|
||||||
|
//Option set Options
|
||||||
|
type Option func(opts *Options)
|
||||||
|
|
||||||
|
//RequestBreaker for protection
|
||||||
|
type RequestBreaker struct {
|
||||||
|
options Options
|
||||||
|
mutex sync.Mutex
|
||||||
|
state State
|
||||||
|
generation uint64
|
||||||
|
counts Counter
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewRequestBreaker return a breaker
|
||||||
|
func NewRequestBreaker() *RequestBreaker {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//State of current switch
|
//State of current switch
|
||||||
type State int
|
type State int
|
||||||
|
|
||||||
|
@ -1,9 +1,51 @@
|
|||||||
package circuit
|
package circuit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var breaker *RequestBreaker
|
||||||
|
|
||||||
func TestBasicBreaker(t *testing.T) {
|
func TestBasicBreaker(t *testing.T) {
|
||||||
|
|
||||||
|
var st Options
|
||||||
|
st.Name = "HTTP GET"
|
||||||
|
st.ReadyToTrip = func(counts counters) bool {
|
||||||
|
failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
|
||||||
|
return counts.Requests >= 3 && failureRatio >= 0.6
|
||||||
|
}
|
||||||
|
|
||||||
|
breaker = NewRequestBreaker(st)
|
||||||
|
|
||||||
|
body, err := Get("https://bing.com/robots.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get wraps http.Get in CircuitBreaker.
|
||||||
|
func Get(url string) ([]byte, error) {
|
||||||
|
body, err := breaker.Execute(func() (interface{}, error) {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return body, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return body.([]byte), nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user