Rust 语言 编写 API 限流中间件 令牌桶算法 + Redis 共享状态

Rust阿木 发布于 2025-06-10 12 次阅读


Rust 语言下的 API 限流中间件:基于令牌桶算法与 Redis 共享状态

在现代互联网应用中,API 限流是一种常见的保护措施,用于防止服务被恶意攻击或过度使用。限流中间件是实现这一功能的关键组件。本文将围绕 Rust 语言,结合令牌桶算法和 Redis 共享状态,实现一个高效的 API 限流中间件。

令牌桶算法

令牌桶算法是一种常见的限流算法,它通过维护一个令牌桶来控制请求的速率。算法的基本思想是:

1. 每隔一定时间(例如每秒)向令牌桶中添加一定数量的令牌。
2. 当请求到达时,如果令牌桶中有足够的令牌,则允许请求通过,并从令牌桶中取出相应数量的令牌。
3. 如果令牌桶中没有足够的令牌,则拒绝请求。

Redis 共享状态

Redis 是一种高性能的键值存储系统,常用于缓存、消息队列等场景。在限流中间件中,我们可以利用 Redis 来存储令牌桶的状态,实现分布式限流。

Rust 限流中间件实现

以下是使用 Rust 语言实现的 API 限流中间件的示例代码:

rust
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use redis::{RedisClient, Commands};

struct TokenBucket {
capacity: usize,
tokens: usize,
last_refill: Instant,
refill_rate: Duration,
}

impl TokenBucket {
fn new(capacity: usize, refill_rate: Duration) -> Self {
TokenBucket {
capacity,
tokens: capacity,
last_refill: Instant::now(),
refill_rate,
}
}

fn consume(&mut self, tokens: usize) -> bool {
if self.tokens >= tokens {
self.tokens -= tokens;
true
} else {
false
}
}

fn refill(&mut self) {
let now = Instant::now();
let elapsed = now.duration_since(self.last_refill);
let tokens_to_add = (elapsed / self.refill_rate).num_digits() as usize;
if tokens_to_add > 0 {
self.tokens = self.capacity.min(self.tokens + tokens_to_add);
self.last_refill = now;
}
}
}

struct RateLimiter {
token_bucket: Arc<Mutex>,
redis_client: RedisClient,
}

impl RateLimiter {
fn new(capacity: usize, refill_rate: Duration, redis_url: &str) -> Self {
let token_bucket = Arc::new(Mutex::new(TokenBucket::new(capacity, refill_rate)));
let redis_client = RedisClient::open(redis_url).unwrap();
RateLimiter {
token_bucket,
redis_client,
}
}

fn limit(&self, key: &str) -> bool {
let mut token_bucket = self.token_bucket.lock().unwrap();
token_bucket.refill();
if token_bucket.consume(1) {
self.redis_client.set(key, "1").unwrap();
true
} else {
false
}
}
}

fn main() {
let rate_limiter = RateLimiter::new(100, Duration::from_secs(1), "redis://127.0.0.1/");

thread::spawn(move || {
loop {
if rate_limiter.limit("api_key") {
println!("Request allowed");
} else {
println!("Request denied");
}
thread::sleep(Duration::from_millis(100));
}
});

thread::spawn(move || {
loop {
let result = rate_limiter.redis_client.get("api_key").unwrap();
if result.is_some() {
println!("Key exists, request rate exceeded");
} else {
println!("Key does not exist, request rate within limit");
}
thread::sleep(Duration::from_millis(100));
}
});

thread::sleep(Duration::from_secs(10));
}

代码解析

1. `TokenBucket` 结构体:表示令牌桶,包含容量、令牌数量、上次填充时间和填充速率。
2. `RateLimiter` 结构体:表示限流器,包含令牌桶和 Redis 客户端。
3. `limit` 方法:检查请求是否被允许,如果允许则向 Redis 中添加一个键值对。
4. `main` 函数:创建限流器实例,并启动两个线程,一个用于模拟请求,另一个用于监控 Redis 中的键值对。

总结

本文介绍了使用 Rust 语言实现基于令牌桶算法和 Redis 共享状态的 API 限流中间件。通过结合 Rust 的并发特性和 Redis 的分布式存储能力,我们能够实现一个高效、可扩展的限流中间件。在实际应用中,可以根据具体需求调整令牌桶的容量和填充速率,以达到最佳的限流效果。