← 中文资源

简体中文版本

Rust 令牌桶限流器

基于 Instant 计算经过时间并补充令牌,容量内允许突发;令牌不足时返回调用方需要等待的 Duration。

阅读英文原文

功能说明

TokenBucket 以 Instant 记录上次补充时间,每次 try_acquire 先按经过秒数乘以速率补充令牌,上限为容量。令牌足够时扣除并返回 Ok(()),不足时用缺少的令牌数除以速率,返回需要等待的 Duration。示例容量 2、速率每秒 4 个,连续三次请求后第三次被拒绝。

关键代码

let now = Instant::now();
let elapsed = now.duration_since(self.last_refill).as_secs_f64();
self.tokens = (self.tokens + elapsed * self.refill_per_second).min(self.capacity);
self.last_refill = now;

min(capacity) 保证长时间空闲后不会积累超过容量的令牌,突发上限始终受控。

使用注意

  • Instant 是单调时钟,不受系统时间调整影响,适合限流。
  • 成本必须大于 0 且不超过容量,示例用 assert! 暴露非法参数。
  • 结构体不是线程安全的,多线程共享需要 Mutex 或原子实现。
  • 返回的等待时间是最早可成功的时间,调用方仍需处理再次竞争失败的情况。
  • 状态只在内存中,重启或扩容都会重置限流额度。

验证方式

示例前两次输出 allowed,第三次输出拒绝并给出约 250 毫秒的等待时间;睡眠 260 毫秒后再次请求通过。把容量改为 1 可观察无突发,把速率调低可观察等待时间变长。