Go 限流与熔断:rate 令牌桶保护下游与简单熔断器实现
test12026-09-130 次阅读
问题背景
调用第三方或下游服务时,突发流量可能把对方打挂。限流(控制自身速率)和熔断(下游异常时快速失败)是两件互补的事:前者防自己发太多,后者防对方已病时还硬扛。
令牌桶限流
package main
import (
"context"
"fmt"
"time"
"golang.org/x/time/rate"
)
func main() {
// 5 QPS,允许突发 10
limiter := rate.NewLimiter(rate.Limit(5), 10)
for i := 0; i < 20; i++ {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
if err := limiter.Wait(ctx); err != nil {
fmt.Println("被限流:", err)
} else {
fmt.Println("处理请求", i, time.Now().Format("15:04:05"))
}
cancel()
}
}
简单熔断器
package main
import (
"errors"
"sync"
"time"
)
type Breaker struct {
mu sync.Mutex
failures int
threshold int
openUntil time.Time
cooldown time.Duration
}
func NewBreaker(threshold int, cooldown time.Duration) *Breaker {
return &Breaker{threshold: threshold, cooldown: cooldown}
}
func (b *Breaker) Call(fn func() error) error {
b.mu.Lock()
if time.Now().Before(b.openUntil) {
b.mu.Unlock()
return errors.New("breaker open")
}
b.mu.Unlock()
if err := fn(); err != nil {
b.mu.Lock()
b.failures++
if b.failures >= b.threshold {
b.openUntil = time.Now().Add(b.cooldown)
}
b.mu.Unlock()
return err
}
b.mu.Lock()
b.failures = 0
b.mu.Unlock()
return nil
}
要点
- rate.Limiter 的突发额度是令牌桶容量,突发后会被限速到设定 QPS。
- 熔断器要设置半开试探,否则冷却后直接全量恢复仍可能再次雪崩;示例为最简版。
- 限流与熔断建议配合使用:限流保护全链路,熔断保护单点故障。
T
test1
文章作者
问题背景 调用第三方或下游服务时,突发流量可能把对方打挂。限流(控制自身速率)和熔断(下游异常时快速失败)是两件互补的...
- 分类
- 技术
- 发布时间
- 2026-09-13
- 字数
- 约 1351 字
- 阅读
- 0 次
