تحديد معدل الطلبات والتحكم في التدفق في Rust: السيطرة على تدفقات البيانات

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

عندما يواجه Rust التحميل الزائد: لماذا تتعطل خدمتك؟

\n\n

تخيل أنك كتبت خدمة عالية التحميل مثالية بلغة Rust. إنها سريعة، تستخدم جميع مزايا التجريدات ذات التكلفة الصفرية وإدارة الذاكرة. ولكن هناك مشكلة - يأتي عميل "شره" ويبدأ في إغراق خادمك بآلاف الطلبات في الثانية. ماذا يحدث؟ هل تتعطل قاعدة البيانات؟ هل يختنق قائمة الانتظار؟ أو الأسوأ من ذلك، هل يتم حظرك من قبل API خارجي تتعامل معه؟

\n\n

في Rust، كما في أي لغة أخرى، لا يمكنك الاستغناء عن تحديد معدل الطلبات والتحكم في التدفق. هذه ليست مجرد "ممارسة جيدة" - إنها مسألة بقاء تطبيقك في بيئة الإنتاج. لكن في Rust هناك ميزة واحدة: نحن نحب أن نفعل كل شيء بكفاءة ومن الصفر. لكن لن تضطر إلى إعادة اختراع العجلة - لدينا مكتبات قوية وأنماط أنيقة.

\n\n

في هذه المقالة، سنشرح كيفية تنفيذ تقييد الطلبات في Rust بشكل صحيح، باستخدام كل من الخوارزميات الكلاسيكية (Token Bucket) والأساليب غير المتزامنة الحديثة. ستتعلم كيفية حماية API الخاص بك من هجمات DDoS، وكيفية عدم تجاوز حدود الخدمات الخارجية، وكيفية كتابة أداة التحكم في التدفق الخاصة بك التي ستعمل بشكل أسرع من Go أو Python.

\n\n

تحديد معدل الطلبات مقابل التحكم في التدفق: ما الفرق؟

\n\n

قبل الغوص في الكود، دعنا نوضح المصطلحات مرة واحدة وإلى الأبد. غالبًا ما يتم الخلط بينهما، لكن الفرق جوهري.

\n\n
    \n
  • تحديد معدل الطلبات - هي سياسة أمنية. أنت تقول: "يمكن للعميل X إجراء 100 طلب كحد أقصى في الدقيقة". إذا تم تجاوز الحد، تقوم بإرجاع 429 Too Many Requests. هذه حماية للواجهة الخلفية الخاصة بك.
  • \n
  • التحكم في التدفق - هي آلية للتحكم في السرعة. أنت تقرر بنفسك السرعة التي تعالج بها الطلبات، حتى لا تفرط في تحميل وحدة المعالجة المركزية أو الإدخال/الإخراج أو قاعدة البيانات. يمكن للعميل إرسال 1000 طلب، لكنك ستعالجها بمعدل 10 في الثانية، والباقي سيتم وضعه في قائمة الانتظار.
  • \n
\n\n

في Rust، يمكن تنفيذ كلا النهجين باستخدام نفس الأدوات، ولكن بمنطق مختلف. سننظر في كليهما.

\n\n

الخوارزميات: Token Bucket و Leaky Bucket

\n\n

أشهر الخوارزميات لتحديد معدل الطلبات هي Token Bucket و Leaky Bucket. إنها بسيطة ولكنها فعالة بشكل لا يصدق.

\n\n

Token Bucket (دلو الرموز)

\n

تخيل دلوًا يتم فيه إسقاط N من الرموز كل ثانية. عندما يأتي طلب، يأخذ رمزًا واحدًا. إذا كان الدلو فارغًا، يتم رفض الطلب. Rust مثالية لتنفيذ هذه الخوارزمية بفضل العمليات الذرية.

\n\n

Leaky Bucket (الدلو المتسرب)

\n

هنا، يحتوي الدلو على ثقب في القاع يتدفق من خلاله عدد ثابت من الطلبات في الثانية. تدخل الطلبات إلى الدلو من الأعلى. إذا فاض الدلو، يتم تجاهل الطلبات الزائدة. هذه الخوارزمية أفضل لتنعيم الأحمال الذروة.

\n\n

في Rust، لن نكتب هذه الخوارزميات يدويًا (على الرغم من أن ذلك مفيد تعليميًا). بدلاً من ذلك، سنستخدم مكتبة governor - المعيار الذهبي لتحديد معدل الطلبات في نظام Rust البيئي.

\n\n

التطبيق العملي: تثبيت Governor

\n\n

مكتبة governor هي تطبيق سريع وغير متزامن وآمن للخيوط لخوارزمية Token Bucket. تدعم كلاً من الأوضاع المتزامنة وغير المتزامنة، وتعمل مع tokio و async-std.

\n\n

نضيف إلى Cargo.toml:

\n\n
[dependencies]\ngovernor = "0.6"\ntokio = { version = "1", features = ["full"] }\n
\n\n

والآن لنكتب أداة بسيطة لتحديد معدل الطلبات لخادم HTTP يعتمد على hyper أو axum. للتبسيط، سنستخدم axum.

\n\n
use axum::{\n    extract::Request,\n    http::StatusCode,\n    middleware::{self, Next},\n    response::Response,\n    routing::get,\n    Router,\n};\nuse governor::{DefaultDirectRateLimiter, Quota, RateLimiter};\n                

المدونات

توصيات الكتب