Kitex限流

2024-01-17T14:21:02+08:00 | 3分钟阅读 | 更新于 2024-01-17T14:21:02+08:00

@

概述

Kitex 提供了内置的服务端限流能力,通过 pkg/limiterpkg/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/负载均衡]] — 客户端侧的流量分发
About Me

没什么想介绍的,一个很大众的码农…

喜欢代码,车,马,真的是 🐎

讨厌别人让我给自己的代码写注释 最厌烦别人的程序没有写注释

目标

学AI,加油!加油!