用户登录

技术文章

外部链接将在新标签页打开。

API 限流与计费系统怎么设计:先定用量记录,再谈流控与账单

一句话回答

限流与计费不应塞进同一个中间件:先在请求路径上写不可变的用量记录,再让限流消费它、让账单异步重算它。限流要分层并区分速率超限与配额耗尽;计费要版本化价格表并能回溯到单条请求;多实例计数、时钟、幂等与降级路径需要显式定义。本文不引用外部来源,算法与结构属通用工程做法,具体阈值与存储选型需按实际流量核实。

稳定的限流与计费系统,关键不在把两个功能合并进一个中间件,而在确定一条顺序:先在请求路径上留下不可变的用量记录,再让限流和计费各自消费这份记录。如果反过来先限流后计量,被拒绝的请求算不算用量、算不算进配额,就会变成随时可以改变的说法。本文没有可引用的外部来源,下面属于通用工程做法与建议,具体阈值、存储选型和一致性方案需按实际流量核实。

一、计量单位决定采样点#

计费对象可能是请求数、输入输出 token 数、字节数或调用时长。计量单位一旦确定,采样点位置也就确定:按请求计数在入口处采样即可;按 token 数必须等上游返回后才能结算;按时长则要处理超时与中断。建议把每次调用拆成“预扣”和“结算”两条记录,共享同一个 request_id,结算数量允许为 0,但要写明原因。

用量记录应追加写、不修改,至少包含:账户、密钥标识、路由、统一时间戳、计量单位、数量、计量口径版本。口径版本很重要,它让“上个月按次计、这个月按 token 计”这种变更不会污染历史数据。

二、限流放在计量之后,并分层#

先计量再限流,好处是被拒绝的请求同样有记录,事后能回答“为什么这个账户在 10:03 被拒了 200 次”。分层通常包括:账户级(预算或月度配额)、密钥级(防止单个泄漏密钥打满账户额度)、路由级(保护昂贵上游)、全局级(保护自身)。

算法适用位置代价
固定窗口计数日/月配额等粗粒度窗口边界允许双倍突发
滑动窗口日志需要精确的小流量场景存储随请求量线性增长
滑动窗口计数常规速率限制近似值,边界有误差
令牌桶允许受控突发的接口需定义速率与桶容量两个参数
漏桶向下游输出平滑流量排队会引入延迟
并发信号量控制同时在途请求与速率限制互补,不能替代

拒绝时要区分语义:速率超限返回 429 并带 Retry-After;配额耗尽应给出明确的错误码和重置时间,让客户端知道重试无用。两者混用会让调用方写出无效的重试逻辑。

三、账单是异步重算出来的#

不要在请求路径上算钱。请求路径只负责写用量事实,账单由异步任务按价格表重算,并在账单中记录引用的价格版本。这样调价、补算、退款都变成“用同一份用量加另一版价格重算”,而不是修改历史账单。对账口径应能下钻到 request_id:用量汇总与账单金额的差异,必须能定位到具体记录,否则对账只是两个数字碰巧相等。

四、容易出问题的边界#

  • 多实例计数:本地计数快但会漂移,集中计数准但有延迟和单点风险。常见折中是本地预限流加集中校准,但误差范围要写进可观测指标,而不是假设它不存在。
  • 时钟:窗口边界和计费时间戳不要依赖各节点本地时钟,应使用统一时间源。
  • 幂等:客户端重试必须带幂等键,否则“预扣成功、结算失败”的重放会造成重复计费。
  • 降级:计量存储不可用时,放行并标记待补,还是直接拒绝,必须显式选择并告警。把这个问题留给异常分支,实际就是默认选择“不确定”。
# 未执行示例:仅示意调用顺序,不是可运行实现
def handle(req):
    rid = req.headers["Idempotency-Key"]   # 占位,需客户端提供
    meter.reserve(rid, account=req.account, unit="request", qty=1)
    if not limiter.allow(account=req.account, route=req.path):
        meter.settle(rid, qty=0, reason="rate_limited")
        return 429, {"error": "rate_limited"}
    resp = upstream.call(req)
    meter.settle(rid, qty=measure(resp))
    return resp

这段伪代码假定计量与限流是两个可独立失败的组件,接口名均为占位。落到具体网关或代理上时,其限流与计量能力需按实际文档核实,本文不声称任何产品支持上述接口。

结论#

设计顺序应当是:用量记录 → 分层限流 → 异步计费 → 对账。限流和计费都依赖同一份用量事实,系统在调价、补算和故障复盘时才有一致的解释。阈值大小、集中计数的实现方式、降级策略的具体取舍,本次材料不足以给出结论,需按实际流量和一致性要求验证。

作者:沐小悠

本文约 5 分钟读完 · 关键词:API 限流设计、API 计费系统、令牌桶、滑动窗口、用量计量

更多文章 GET 示例接口

「」标签下的其他文章