2. 限流基础概念
在催收与 Model Serving 场景中,限流(Rate Limiting)是保障系统稳定性的第一道防线。本章从定义、目的与核心算法三个维度建立限流知识体系,为后续的熔断与模型服务限流策略打下基础。
2.1 限流定义
限流是一种通过控制单位时间内允许通过的请求数量、并发数或数据量,来防止系统过载的流量管控手段。在催收系统中,限流作用于以下三个关键层面:
- API 网关层:限制外部催收机构、催收员客户端的请求速率。
- 业务服务层:控制案件分配、策略计算、外呼触发的并发量。
- 模型推理层:限制模型 Serving 的 QPS(每秒查询数)与批处理大小。
催收场景提示: 催收系统在月初、月末或节假日前后常出现流量尖峰。限流不是拒绝所有超量请求,而是让系统在可控负载下优先处理高优先级案件(如逾期 30+ 天、大额欠款)。
2.2 限流目的
限流的核心目标可归纳为两大维度:
| 目的维度 | 具体说明 | 催收场景示例 |
|---|---|---|
| 保护系统 | 防止突发流量击穿数据库、缓存、模型推理服务等后端资源,避免级联故障。 | 催收员批量导入案件时,限制导入接口的 TPS,防止数据库连接池耗尽。 |
| 公平使用 | 确保多个租户、多个催收机构或模型版本之间公平分配服务资源,防止单一来源抢占全部容量。 | 两家催收机构同时调用评分模型,限流保证每家最多占用 50% 的模型推理容量。 |
| 成本控制 | 在云原生架构中,限流直接关联计算资源(GPU/CPU)的预算管控。 | 模型 Serving 按 QPS 计费,限流防止因流量突增导致月度推理成本超支。 |
2.3 限流常见算法
业界主流限流算法包括令牌桶、漏桶与计数器三种。以下从原理、适用场景与催收适配性三个维度进行对比。
2.3.1 令牌桶算法(Token Bucket)
令牌桶以固定速率向桶中添加令牌,每个请求需消耗一个令牌才能被处理。桶容量限制最大突发流量。
- 核心参数:令牌填充速率(r)、桶容量(b)。
- 优势:允许一定程度的突发流量,适合模型推理等需要容忍短时峰值的场景。
- 劣势:突发流量可能超过后端实际处理能力,需配合熔断使用。
- 催收适用:催收员批量查询案件详情时,允许短时突发查询,但长期平均速率受控。
2.3.2 漏桶算法(Leaky Bucket)
漏桶将请求放入队列,以恒定速率从队列中取出处理。桶满时新请求被直接丢弃。
- 核心参数:漏出速率(r)、桶容量(b)。
- 优势:输出流量绝对平滑,适合保护数据库等对写入速率敏感的后端。
- 劣势:无法应对突发流量,可能导致请求排队超时。
- 催收适用:催收外呼记录写入数据库时,使用漏桶保证写入速率不超过数据库 IOPS 上限。
2.3.3 计数器算法(Counter / Fixed Window)
计数器在固定时间窗口(如 1 秒)内累计请求数,超过阈值则拒绝后续请求。窗口结束后计数器重置。
- 核心参数:时间窗口大小(w)、窗口内最大请求数(n)。
- 优势:实现简单,内存占用极低。
- 劣势:存在窗口边界流量突刺问题(临界效应),精度较低。
- 催收适用:非核心监控接口(如健康检查)的简易限流,对精度要求不高的场景。
算法选型建议: 在催收 Model Serving 场景中,推荐令牌桶作为默认算法——它既能容忍催收员操作带来的短时突发,又能通过桶容量限制最大并发推理请求,避免 GPU 显存溢出。漏桶更适合下游存储层限流,计数器仅用于低精度监控接口。
2.4 三种算法对比总览
| 对比维度 | 令牌桶 | 漏桶 | 计数器 |
|---|---|---|---|
| 突发处理能力 | 允许突发(受桶容量限制) | 不允许突发 | 窗口内允许突发 |
| 输出流量形态 | 平均速率可控,可突发 | 绝对平滑 | 阶梯状,窗口边界不平滑 |
| 实现复杂度 | 中等 | 中等 | 低 |
| 内存开销 | 低(仅维护桶状态) | 低(需维护队列) | 极低(仅计数器) |
| 催收 Model Serving 推荐度 | ★★★★★ | ★★★☆☆ | ★★☆☆☆ |
2.5 限流算法工作流程对比(SVG)
下图展示三种限流算法在催收请求处理中的核心流程差异:
2.6 限流在催收 Model Serving 中的落地要点
将限流算法应用于催收模型推理服务时,需关注以下工程要点:
- 令牌桶容量与模型批处理大小对齐:桶容量 b 应 ≥ 模型最大批处理大小,避免因限流导致批处理无法填满,降低 GPU 利用率。
- 限流与超时联动:被限流的请求不应无限等待,需设置合理的排队超时时间(如 500ms),超时后返回 429 Too Many Requests。
- 多级限流策略:在网关层(全局 QPS 限流)与服务层(每个模型版本独立限流)同时部署,形成双层保护。
- 动态限流配置:催收业务流量具有明显的日周期特征,建议支持按时间段调整限流阈值(如白天催收高峰期提高模型推理限流上限)。
常见陷阱: 仅依赖单层限流。例如只在网关层限流但未对模型 Serving 实例做限流,当网关限流配置错误或绕过网关的直连请求涌入时,模型服务仍可能被击穿。正确的做法是网关层 + 服务层双重限流。
2.7 限流配置示例(令牌桶 + 漏桶组合)
以下是一个催收系统中针对模型推理服务(令牌桶)与数据库写入(漏桶)的限流配置伪代码:
# 模型推理服务限流 —— 令牌桶
rate_limiter_model = TokenBucket(
rate=100, # 每秒填充 100 个令牌
capacity=200, # 桶容量 200,允许短时突发
timeout_ms=500 # 等待令牌超时 500ms
)
# 催收外呼记录写入限流 —— 漏桶
rate_limiter_db = LeakyBucket(
leak_rate=50, # 每秒处理 50 条记录
capacity=100, # 队列容量 100
drop_policy="tail_drop" # 队列满时丢弃最早请求
)
# 请求处理流程
def handle_collection_request(request):
# 1. 模型推理前获取令牌
if not rate_limiter_model.try_acquire():
return HTTPStatus.TOO_MANY_REQUESTS, "模型推理限流,请稍后重试"
# 2. 执行模型推理
score = model.predict(request.features)
# 3. 写入外呼记录前检查漏桶
if not rate_limiter_db.try_acquire():
# 记录降级:写入本地日志,异步补偿
log_to_local_file(request, score)
return HTTPStatus.OK, {"score": score, "write_status": "deferred"}
# 4. 正常写入数据库
db.insert(collection_record(request, score))
return HTTPStatus.OK, {"score": score, "write_status": "written"}
生产环境建议: 上述代码中的限流器应使用 Redis 或本地原子计数器实现分布式一致性。在 Kubernetes 部署的 Model Serving 中,推荐使用 Envoy 的全局速率限制过滤器 或 Istio 的 RateLimiter 作为网关层限流,服务层使用 Guava RateLimiter(Java)或 aioredis-rate-limiter(Python)实现实例级限流。