限流不生效是因为只配置了yaml中的limit字段,但未在rpc服务启动时显式注册限流中间件:rpcx需调用server.use(rpcx.newratelimitingmiddleware(...)),grpc需注册unaryinterceptor。

Go-Zero 里 rpcx 和 grpc 限流配置为什么没生效?
限流不生效,大概率不是框架坏了,而是你配在了错误的位置。Go-Zero 的限流分两层:服务端入口(Rest 或 RPC 网关层)和 RPC 方法内部(rpcx 或 grpc 服务端),二者逻辑独立。
常见错误是只在 etc/*.yaml 里写了 Limit 配置,但没在 RPC 服务启动时显式启用限流中间件。
-
rpcx服务需在NewServer后调用server.Use(rpcx.NewRateLimitingMiddleware(...)),否则limit字段纯属摆设 -
grpc服务同理,必须注册grpc.UnaryInterceptor对应的限流拦截器,比如middleware.NewRateLimitInterceptor() - 注意
rpcx默认使用token bucket,而grpc示例中常用sliding window,算法不同导致压测表现差异大
熔断器 Breaker 触发后为啥一直拒绝请求?
Go-Zero 的 Breaker 默认策略是「半开→失败→关闭→失败→熔断」,但一旦进入 open 状态,它不会自动探活,除非你手动调用 breaker.Allow() 或等超时时间过去(默认 60s)。
真实场景下,下游恢复快于熔断窗口,会导致上游白白丢流量。
- 检查
Breaker初始化参数:timeout(熔断持续时间)、interval(半开探测间隔)、proba(半开试探概率) - 别依赖默认值 ——
timeout: 60s在秒级服务里太长,建议设为10s起步 - 如果下游是 DB 或缓存,建议配合
fallback函数返回兜底数据,而不是直接 panic 或 error
go-zero 内置治理指标怎么接入 Prometheus?
Go-Zero 自带 metrics 模块,但默认不暴露 HTTP 接口,也不会自动注册到 Prometheus 的 /metrics 路径,得自己搭桥。
关键点在于:指标收集和指标暴露是两个动作,缺一不可。
- 服务启动时要调用
metrics.Register()(通常在main.go初始化阶段) - 必须单独起一个 HTTP server(比如用
http.ListenAndServe(":9091", nil)),并在 handler 中注入promhttp.Handler() - 注意路径别写错 ——
promhttp.Handler()默认只响应/metrics,别配成/actuator/metrics这类 Spring 风格路径 - RPC 服务默认不打点
rpc_latency_ms,需要在每个handler手动调用metrics.RecordDuration(...)
高并发下 redis 连接池耗尽、context deadline exceeded 频发
这不是 Redis 慢,是 Go-Zero 的 redis 客户端默认连接池太小(MaxIdle = 2,MaxActive = 10),QPS 上千就容易打满。
更麻烦的是,它不支持运行时动态扩容,只能初始化时定死。
- 在
cache.NewRedis或redis.NewRedis初始化时,显式传入redis.RedisConf{PoolSize: 100} - 别信文档里“够用”的说法 ——
PoolSize建议设为预估峰值 QPS × 平均 Redis 耗时(秒),比如 5000 QPS × 0.02s = 100 - 如果用了
redis.Cluster,注意Cluster模式下PoolSize是 per-node 的,总连接数 = node 数 × PoolSize - 加了连接池还不够,记得给所有
redis.Do调用包一层ctx, cancel := context.WithTimeout(ctx, 300*time.Millisecond)











