تحديد معدل الطلبات في Rust: نظرة عامة على المكتبات والأدوات
تحديد معدل الطلبات (Rate limiting) هو آلية حاسمة لحماية خدمات الويب من الأحمال الزائدة وهجمات DDoS وسوء الاستخدام. في نظام Rust البيئي، تتوفر عدة مكتبات ناضجة لتنفيذ تحديد معدل الطلبات: من الخوارزميات منخفضة المستوى إلى middleware الجاهزة لأطر الويب الشائعة. في هذه المقالة، سنستعرض ثلاثة أساليب رئيسية: 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. Middleware لأطر الويب
تعمل middleware الجاهزة على تبسيط دمج تحديد معدل الطلبات في خوادم الويب المبنية على Actix و Axum بشكل كبير.
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")), }}