Senior
What mechanisms are there to protect against slow external services? What is a Circuit Breaker?
sobes.tech AI
Answer from AI
To protect against slow external services in Go and in general, the following mechanisms are used:
- Timeouts — limiting the waiting time for a response from the service.
- Retries with exponential backoff to avoid overloading the service.
- Circuit Breaker — a pattern that prevents constant calls to a non-responsive or slow service.
- Bulkhead — resource isolation for different services to prevent a failure in one from affecting the entire system.
What is a Circuit Breaker?
A Circuit Breaker is a pattern that monitors the state of calls to an external service and, upon detecting a high number of errors or timeouts, "opens" the circuit, i.e., temporarily blocks further calls to that service. This allows:
- To avoid excessive load on a non-responsive service.
- To return errors to the client faster, without waiting.
- To allow the service to recover, after which the Circuit Breaker automatically "closes" the circuit and resumes calls.
An example of implementing a Circuit Breaker in Go can be done using libraries such as github.com/sony/gobreaker:
import (
"fmt"
"net/http"
"time"
"github.com/sony/gobreaker"
)
func main() {
cb := gobreaker.NewCircuitBreaker(gobreaker.Settings{
Name: "HTTP GET",
MaxRequests: 3,
Interval: 60 * time.Second,
Timeout: 30 * time.Second,
ReadyToTrip: func(counts gobreaker.Counts) bool {
return counts.ConsecutiveFailures > 5
},
})
body, err := cb.Execute(func() (interface{}, error) {
resp, err := http.Get("https://example.com/api")
if err != nil {
return nil, err
}
defer resp.Body.Close()
return "success", nil
})
if err != nil {
fmt.Println("Request failed or circuit open:", err)
} else {
fmt.Println("Request succeeded:", body)
}
}
Thus, the Circuit Breaker helps make the system more resilient to external service failures.