在微服务世界,网关就像城市的交通枢纽。没有智能调度,轻则拥堵,重则瘫痪。你是否遇到过某个下游服务“罢工”,导致全站雪崩?或者某个爬虫一夜之间把接口刷爆?今天,我们用 Go 带你打造一个“会思考”的网关——它能自动熔断异常实例,还能根据 Consul 配置动态调整限流策略,实现真正的自愈与弹性!
一、熔断器:让网关有“自我保护”本能
我们选用 mercari/go-circuitbreaker 作为熔断核心。优势如下:
-
高并发友好:内部无锁或极少锁,性能极佳
-
策略灵活:支持失败率、连续错误等多种熔断策略
-
状态可观测:每次状态变更可回调,方便监控和报警
-
半开自愈:自动探测恢复,避免“假死”
想象你是高速公路收费站站长,发现某条车道(后端实例)连续出事故,你会暂时封闭它(Open),等一会儿派几辆车试探(Half-Open),如果没问题再重新开放(Closed)。
关键代码示例:
func NewCircuitBreakerWithConfig(cfg CircuitBreakerConfig) *circuitbreaker.CircuitBreaker {
cb := circuitbreaker.New(
circuitbreaker.WithCounterResetInterval(cfg.CounterResetInterval),
circuitbreaker.WithHalfOpenMaxSuccesses(cfg.HalfOpenMaxSuccesses),
circuitbreaker.WithTripFunc(
circuitbreaker.NewTripFuncFailureRate(cfg.FailureRateWindow, cfg.FailureRateThreshold),
),
circuitbreaker.WithOnStateChangeHookFn(func(from, to circuitbreaker.State) {
fmt.Printf("[CB][%s] 状态变更: %s -> %s\n", cfg.Name, from, to)
}),
)
return cb
}
每个后端实例拥有独立熔断器,状态清晰可见,异常自动隔离。
二、动态限流:让网关“见人下菜碟”
限流不再是死板的 QPS 数字!easyms.golang 支持:
-
按 IP 段限流:内网、海外 IP 可分别限流
-
按 UserAgent 限流:爬虫、APP、浏览器各有不同规则
-
规则热更新:所有规则可在 Consul 配置,秒级生效,无需重启
网关像一个聪明的门卫,能识别来访者的“身份证”(IP)和“穿着打扮”(UserAgent),为不同人群设定不同通行速度,遇到新规则还能立即生效。
配置示例(YAML):
rate_limit:
ip_limits:
- cidr: "192.168.1.0/24"
rate: 20
burst: 40
ua_limits:
- pattern: ".*Chrome.*"
rate: 50
burst: 100
default_rate: 100
default_burst: 200
核心代码:
func (lm *LimiterManager) SyncFromAppConfig() {
cfg := config.GetAppConfig()
if cfg == nil || cfg.RateLimit == nil {
return
}
lm.mu.Lock()
defer lm.mu.Unlock()
// 解析并重建限流规则
// ...
}
每 10 秒自动同步一次配置,限流策略随需应变。
三、网关全流程
- 请求到达 → 先通过限流门卫(IP/UA/默认多重限流)
- 分发到后端实例 → 每个实例独立熔断,异常自动隔离
- 配置变更 → Consul 更新规则后,网关秒级生效,真正“活”的系统!
架构示意:
┌─────────────┐
│ Client │
└─────┬───────┘
│
▼
┌─────────────┐
│ Gateway │
│ ┌─────────┐ │
│ │ 限流器 │ │ ← 动态规则(Consul/YAML)
│ └─────────┘ │
│ ┌─────────┐ │
│ │ 熔断器 │ │ ← 每实例独立
│ └─────────┘ │
└─────┬───────┘
│
▼
┌─────────────┐
│ Backend │
└─────────────┘
源码地址:
- GitHub:github.com/louis-xie-p…
- Gitee: gitee.com/louis_xie/e…
你觉得微服务网关最难的部分是什么?评论区说出你的故事。后续easyms将在其基础上全面完善网关的功能,敬请关注后续文章。 部分相关文章(请结合前期相关文章更深入的了解easyms):