1. 程式人生 > >Circuit Breaker pattern

Circuit Breaker pattern

In the previous post, i have implemented simple circuit-breaker pattern with Java, and today i will do it with Go

Talk about advanced of Go

+ Golang has great concurrency, the memory required for creating thread is very light.

+ Code is simple and very clean, easy to lean.

+ Appropriate and effective for service application.

+ ……

Focus on main issue of this post, i will talk about step by step to implement breaker pattern

+ Create package and file breaker.go into the folder

+ Define state service and state breaker type State inttype State int type StateService int const (    STATE_CLOSE  State        = 1    STATE_HALF_OPEN     State        = 2    STATE_OPEN          State        = 3    SERVICE_AVAILABLE   StateService = 1    SERVICE_UNAVAILABLE StateService = 0 )

+ Define Breaker, BreakerEvent, OptionsConfig, CounterResult type CounterResult struct {    TotalRequests uint32    TotalSucceses uint32    TotalFailures uint32    TotalRejects uint32 }

type Breaker struct {    options OptionsConfig    counter CounterResult    events []chan BreakerEvent    state State    consecFailures uint32 }

type BreakerEvent struct {    Code StateService    Message string }

type OptionsConfig struct {    Attempts uint32    TimeoutState time.Duration    LimitFailure uint32    MaxRequests uint32    NameService string } + Create new instance breaker func NewBreaker(options *OptionsConfig) *Breaker { if options == nil {    options = &OptionsConfig{} } if options.Attempts == 0 {    options.Attempts = 3 } if options.TimeoutState == 0 {    options.TimeoutState = 4 * time.Second } if options.LimitFailure == 0 {    options.LimitFailure = 5 } if options.MaxRequests == 0 {    options.MaxRequests = 10000000 } if options.NameService == "" {    options.NameService = strconv.Itoa(int(time.Now().UnixNano())) } return &Breaker{options: *options, counter: CounterResult{}, state: STATE_CLOSE, consecFailures: 0} }

+ Allow other services subscribe event // other services subcriber func (cb *Breaker) Subcriber() <-chan BreakerEvent {    evenReader := make(chan BreakerEvent)    outputChannel := make(chan BreakerEvent, 100)    go func() {    for event := range evenReader {       select {       case outputChannel <- event:       default:<-outputChannel       outputChannel <- event       }    }    }()    cb.events = append(cb.events, evenReader)    return outputChannel }

+ Create execute handle // execute handle func (cb *Breaker) Execute(handle func() ResponseCommand, timeout time.Duration) ResponseCommand {    // add request    atomic.AddUint32(&cb.counter.TotalRequests, 1)    response := ResponseCommand{}    // Reject all invoke when current state is OPEN    if cb.IsOpen() {    cb.Reject()       response.Error = cb.ErrorServiceUnavailable()       response.Data = nil       return response    }    // run handle immediate and execute time is unlimited    if timeout == 0 {       response = handle()    } else {    // run handle with time execute is limited    c := make(chan ResponseCommand, 1)    go func() {       c <- handle()    }()    select {       case r := <-c:       response = r       close(c)       case <-time.NewTimer(timeout).C:       response.Error = cb.ErrorTimeoutExecute()       response.Data = nil    }    }    // check for any errors    if response.Error != nil {       cb.Failure()    } else {       cb.Success()    }    return response } You can reference full source and demo at : circuit-breaker-go

Advertisements

Like this:

Like Loading...