Rust中的速率限制:库与工具概览
速率限制(请求频率限制)是保护Web服务免受过载、DDoS攻击和滥用的关键机制。在Rust生态系统中,有多个成熟的库可用于实现速率限制:从底层算法到流行Web框架的现成中间件。本文将探讨三种核心方法:governor(GCRA算法)、leaky-bucket(漏桶算法)以及与Actix/Axum的集成。
1. governor库——GCRA算法
governor是Rust中最流行的速率限制库,基于通用信元速率算法(GCRA)。该算法用于网络协议,可灵活配置峰值负载和平均速率。
主要特性:
- 支持多种键(IP、User-Agent、API密钥)
- 可配置的突发流量(burst)
- 通过
tokio或async-std实现异步操作 - 无锁线程安全
设置每分钟100个请求、突发20个的示例:
use governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};use std::num::NonZeroU32;use std::time::Duration;
#[tokio::main]async fn main() { // 限制:每分钟100个请求,突发20个 let quota = Quota::with_period(Duration::from_secs(60)) .unwrap() .allow_burst(NonZeroU32::new(20).unwrap()); let limiter = DefaultKeyedRateLimiter::::new(quota); // 检查用户"user123" match limiter.check_key("user123") { Ok(_) => println!("请求已允许"), Err(_) => println!("超出限制,状态码429"), }} 2. leaky-bucket库——漏桶算法
漏桶算法在leaky-bucket库中实现。它模拟一个水桶,请求注入其中并以恒定速率漏出。适用于平滑峰值负载。
特点:
- 简单模型:容量为N个请求的桶
- 泄漏速率:每秒请求数
- 支持最大等待请求数
每秒5个请求、桶容量为10的示例:
use leaky_bucket::RateLimiter;use std::time::Duration;
#[tokio::main]async fn main() { let limiter = RateLimiter::builder() .initial(10) // 初始令牌数 .max(10) // 桶的最大容量 .interval(Duration::from_millis(200)) // 每200毫秒补充一次 .build(); // 尝试获取令牌 if limiter.try_acquire().is_ok() { println!("请求已处理"); } else { println!("桶已空,拒绝请求"); }}3. Web框架中间件
现成的中间件大大简化了在Actix和Axum Web服务器中集成速率限制的过程。
Actix + governor
use actix_web::{web, App, HttpServer, HttpRequest, HttpResponse, middleware::from_fn};use governor::{DefaultKeyedRateLimiter, Quota};use std::num::NonZeroU32;use std::time::Duration;
async fn rate_limit_middleware( req: HttpRequest, limiter: web::Data<DefaultKeyedRateLimiter<String>>,) -> Result<HttpResponse, actix_web::Error> { let client_ip = req.peer_addr() .map(|addr| addr.to_string()) .unwrap_or_default(); match limiter.check_key(&client_ip) { Ok(_) => Ok(HttpResponse::Ok().body("OK")), Err(_) => Ok(HttpResponse::TooManyRequests().body("Too Many Requests")), }}