分布式系统中限流和熔断机制至关重要,Go 框架提供了广泛的实现机制。限流旨在防止过载,例如限制每秒 HTTP 请求数量。熔断则在服务失败或响应时间过长时,暂时阻止对服务的访问,以避免级联故障。
Go 框架限流和熔断在分布式系统中的应用
在现代分布式系统中,限流和熔断机制对于确保系统稳定性和弹性至关重要。Go 语言提供了广泛的框架来简化这些机制的实现。
限流
限流机制旨在防止系统因过载而崩溃。
import ( "context" "github.com/golang/groupcache/lru" "time" ) // LimitRequests 限制每秒请求 func LimitRequests(ctx context.Context, maxRequests, d time.Duration) (func(), error) { l := lru.New(maxRequests) go func() { for { time.Sleep(d) l.Purge() } }() return func() bool { return l.Add(0, nil) != nil }, nil }
实战示例:
使用限流来限制每秒处理的 HTTP 请求数量:
import ( "github.com/buaazp/fasthttprouter" "time" ) func main() { limiter, err := LimitRequests(context.Background(), 10, time.Second) if err != nil { log.Fatal(err) } router := fasthttprouter.New() router.GET("/", func(ctx *fasthttp.RequestCtx) { if limiter() { ctx.Error("Too many requests", fasthttp.StatusTooManyRequests) return } // 处理请求... }) server.ListenAndServe(":8080") }
熔断
熔断机制旨在在服务失败或响应时间过长时暂时阻止对服务的访问。
import ( "context" "errors" "sync" "time" ) // CircuitBreaker 熔断器 type CircuitBreaker struct { sync.Mutex state State closedAt time.Time failedReq int successReq int } // State 熔断状态 type State int const ( Closed State = iota HalfOpen Open ) // Trip 熔断 func (cb *CircuitBreaker) Trip() { cb.Lock() defer cb.Unlock() cb.failedReq++ cb.state = Open cb.closedAt = time.Now().Add(time.Minute) } // Close 关闭熔断 func (cb *CircuitBreaker) Close() { cb.Lock() defer cb.Unlock() cb.state = Closed cb.closedAt = time.Now() } // Allow 通过请求 func (cb *CircuitBreaker) Allow() error { cb.Lock() defer cb.Unlock() now := time.Now() if cb.state == Open && cb.closedAt.After(now) { return errors.New("circuit open") } if cb.state == HalfOpen { cb.state = Closed cb.successReq++ } return nil }
实战示例:
使用熔断器来保护对外部服务的调用:
import ( "errors" "time" "github.com/sony/gobreaker" "github.com/uber/jaeger-client-go" ) var ( jaegerCloser jaeger.Closer cb = gobreaker.NewCircuitBreaker(gobreaker.Settings{ // 连续请求失败才会熔断 Interval: 10 * time.Second, }) fallbackCallCount int ) func MakeRemoteCall() (string, error) { err := cb.Execute(func() (string, error) { return "some result", nil }) if err != nil { fallbackCallCount++ return "fallback result", nil } return "result", nil }