概述
Kitex 提供了内置的服务端限流能力,通过 pkg/limiter 和 pkg/limit 包实现,无需依赖外部组件(如 Sentinel)。限流在传输层通过 InboundHandler 拦截器生效,在请求到达业务 handler 之前就进行流量控制。
限流类型
Kitex 支持两种核心限流维度:
| 类型 | 接口 | 作用 | 拒绝错误 |
|---|---|---|---|
| 连接数限流 | ConcurrencyLimiter | 限制服务端并发连接总数 | ErrConnOverLimit |
| QPS 限流 | RateLimiter | 限制每秒请求处理速率 | ErrQPSOverLimit |
1. 连接数限流 (ConcurrencyLimiter)
基于原子计数器实现,跟踪当前活跃连接数:
type ConcurrencyLimiter interface {
Acquire(ctx context.Context) bool // 获取连接许可,返回 true 表示允许
Release(ctx context.Context) // 释放连接许可
Status(ctx context.Context) (limit, occupied int) // 查询当前状态
}
Acquire():在连接建立时调用,原子递增计数器,判断是否超过上限Release():在连接关闭时调用,原子递减计数器- 当
limit <= 0时视为不限流模式,始终放行
2. QPS 限流 (RateLimiter)
基于固定窗口 + Token Bucket 算法实现:
type RateLimiter interface {
Acquire(ctx context.Context) bool // 获取令牌
Status(ctx context.Context) (max int, current int, interval time.Duration) // 查询状态
}
算法原理:
- 将 1 秒划分为多个时间窗口,每个窗口预分配一定数量的 token
- 使用
time.Ticker按窗口周期 refill token(上限为总 limit) Acquire()时原子递减 token 计数,token 耗尽则拒绝
示例:limit=1000, interval=100ms
每 100ms 窗口分配 1000 / (1000/100) = 100 个 token
每次 Acquire 消耗 1 个 token
Ticker 每 100ms 补充一次,上限 1000
3. 动态更新 (Updatable)
两个限流器都支持运行时动态调整限流阈值:
type Updatable interface {
UpdateLimit(limit int) // 动态修改限流值
}
配合 [[配置管理]] 可实现热更新,无需重启服务。
服务端集成
基本用法
通过 server.WithLimitOption 在服务启动时配置:
import "github.com/cloudwego/kitex/pkg/limit"
svr := kitex.NewServer(YourServiceImpl{},
server.WithLimitOption(&limit.Option{
MaxConnections: 10000, // 最大并发连接数
MaxQPS: 5000, // 最大 QPS
}),
)
拦截器链路
限流通过 pkg/remote/bound.limiterInbound 作为 Inbound Handler 嵌入传输层:
客户端请求
↓
OnActive() → connLimit.Acquire() // 连接建立时检查连接数
↓
OnRead() → qpsLimit.Acquire() // 读取请求头后检查 QPS(默认 pre-decode)
↓
OnMessage() → qpsLimit.Acquire() // 解码完成后检查 QPS(可选 post-decode)
↓
业务 Handler // 通过所有限流检查后进入业务逻辑
↓
OnInactive() → connLimit.Release() // 连接关闭时释放
关键参数:qpsLimitPostDecode
false(默认):在请求解码前进行 QPS 限流,保护服务端免受反序列化开销影响true:在请求解码后进行 QPS 限流,可根据请求内容做更精细的判断
拒绝处理
当限流触发时,返回标准 Kitex 错误:
// ErrConnOverLimit
// base: "request over limit"
// cause: "too many connections"
// ErrQPSOverLimit
// base: "request over limit"
// cause: "request too frequent"
可在客户端或网关层通过 errors.Is(err, kerrors.ErrConnOverLimit) 识别限流错误,配合 [[重试]] 机制做降级处理。
架构总结
┌─────────────────────────────────────────────┐
│ Kitex Server │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ limiterInbound (Handler) │ │
│ │ ┌────────────┐ ┌──────────────┐ │ │
│ │ │ConnLimiter │ │ QPSLimiter │ │ │
│ │ │(原子计数器) │ │(固定窗口+ │ │ │
│ │ │ │ │ TokenBucket) │ │ │
│ │ └─────┬──────┘ └──────┬───────┘ │ │
│ └────────┼────────────────┼────────────┘ │
│ ▼ ▼ │
│ 连接数检查 QPS 检查 │
│ ▼ ▼ │
│ ┌─────────────────────┐ │
│ │ Business Handler │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────┘
与其他方案的对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| Kitex 内置限流 | 零依赖、开箱即用、轻量 | 功能较基础,无分布式能力 |
| Apache Sentinel | 分布式、实时监控、规则中心 | 需要额外部署 Sentinel Dashboard |
| 自定义 Middleware | 完全可控、灵活 | 需自行实现算法和状态管理 |
相关笔记
- [[Kitex/中间件]] — 自定义限流可通过 Middleware 实现
- [[Kitex/重试]] — 限流拒绝后的客户端重试策略
- [[Kitex/超时]] — 与限流配合的超时配置
- [[Kitex/负载均衡]] — 客户端侧的流量分发