问题: go 框架如何处理限流和熔断?答案:限流:基于令牌的算法:gin-tonic 和 ratelimit 库。基于计数的算法:heap 库。熔断:hystrix 库:功能强大,提供错误百分比阈值和熔断状态管理。resilient 库:提供了健壮的熔断功能,包括滑动窗口和最小调用次数。
Go 框架如何处理限流和熔断
简介
限流和熔断是微服务架构中至关重要的概念。限流保护系统免受过载,而熔断机制可快速隔离出现故障的服务。Go 语言提供了丰富的框架,用于轻松实现这些机制。
立即学习“go语言免费学习笔记(深入)”;
限制流
基于令牌的算法
-
Gin-tonic: 使用滑动窗口算法限制 API 请求速率。
package main import ( "net/http" "time" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.Use(gin.RateLimit(5, 1*time.Second)) // 限制每秒最多 5 个请求 }
-
ratelimit: 提供基于令牌桶算法的库。
package main import ( "time" "github.com/jakekeeys/ratelimit" ) func main() { limiter := ratelimit.New(5, 1*time.Second) // 限制每秒最多 5 个请求 // ... 使用limiter执行受限的操作 ... }
基于计数的算法
-
heap: 使用堆算法实现基于计数的速率限制。
package main import ( "heap/heap" "time" ) type request struct { timestamp time.Time } type heap []request func (h heap) Len() int { return len(h) } func (h heap) Less(i, j int) bool { return h[i].timestamp.Before(h[j].timestamp) } func (h heap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *heap) Push(x interface{}) { *h = append(*h, x.(request)) } func (h *heap) Pop() interface{} { old := *h n := len(old) x := old[n-1] *h = old[0 : n-1] return x } func main() { reqLim := heap{ request{timestamp: time.Now()}, request{timestamp: time.Now()}, request{timestamp: time.Now()}, } rateLimit := 5 heap.Init(&reqLim) for i := 0; i < 10; i++ { if reqLim.Len() >= rateLimit { // ... 执行速率受限的操作 ... } reqLim.Push(request{timestamp: time.Now()}) } }
熔断
-
Hystrix: Apache 提供的强大的熔断库。
package main import ( "errors" "time" "github.com/afex/hystrix-go/hystrix" ) func main() { hystrix.ConfigureCommand("myCommand", hystrix.CommandConfig{ Timeout: 1000 * time.Millisecond, MaxConcurrentRequests: 10, ErrorPercentThreshold: 20, SleepWindow: 5 * time.Second, }) output := make(chan error) go func() { status := hystrix.GetCommand("myCommand").Run(func() error { // ... 执行需要保护的操作 ... return errors.New("error") }) if status.IsFailed() { output <- status.Error } close(output) }() // ... 使用 output 响应熔断状态 ... }
-
resilient: 提供健壮的熔断功能。
package main import ( "errors" "time" "github.com/resilience4j/resilience4go/circuitbreaker" ) func main() { breaker := circuitbreaker.New("myCircuit", circuitbreaker.Config{ Timeout: time.Millisecond * 1000, MaxConcurrentCalls: 10, SlidingWindowSize: 5, MinimumNumberOfCalls: 5, ErrorThresholdPercentage: 20, WaitDurationInOpenState: time.Second * 5, }) result := breaker.Execute(func() (interface{}, error) { // ... 执行需要保护的操作 ... return nil, errors.New("error") }) // ... 使用 result 响应熔断状态 ... }