هندسة الفوضى لـ Rust: كيف تجعل التطبيق غير قابل للكسر

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

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

ابدأ الدورة

خادم Rust الخاص بك مثالي؟ دعنا نتحقق من ذلك



لقد كتبت خادمًا بلغة Rust يعالج آلاف الطلبات في الثانية. المترجم راضٍ، clippy صامت، والاختبارات ناجحة. ولكن ماذا سيحدث إذا انقطعت قاعدة البيانات فجأة؟ أو إذا بدأت بطاقة الشبكة في "التعطل"؟ أو إذا امتلأ القرص؟



في الاختبار التقليدي، نتحقق من أن الكود يعمل كما هو مقصود. هندسة الفوضى (Chaos engineering) تدور حول شيء آخر: نتحقق من أن النظام يبقى على قيد الحياة رغم كل شيء. و Rust، بتركيزها على الموثوقية والأداء، هي المنصة المثالية لمثل هذه التجارب.



هذه المقالة ليست إعادة سرد مملة للوثائق. سننتقل من النظرية إلى التطبيق العملي: سأوضح كيفية دمج هندسة الفوضى لتطبيقات Rust باستخدام أدوات وكود حقيقي.



ما هي هندسة الفوضى ولماذا هي مهمة لمطور Rust؟



هندسة الفوضى هي نظام تجارب على الأنظمة الموزعة، تهدف إلى اكتشاف نقاط ضعفها قبل أن تظهر في بيئة الإنتاج. Netflix، التي تعتبر رائدة هذا النهج، تستخدم أداة Chaos Monkey لإيقاف تشغيل الخوادم بشكل عشوائي.



لماذا هذا مهم تحديدًا لـ Rust؟ لأن Rust غالبًا ما تُختار للأنظمة الحيوية:

  • خدمات الشبكة (البروكسي، موازنات التحميل، بوابات API)
  • الأنظمة المضمنة (إنترنت الأشياء، السيارات)
  • عُقد البلوكتشين والأنظمة المالية
  • معالجة البيانات المتدفقة


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



أدوات هندسة الفوضى في نظام Rust البيئي



على الرغم من أن نظام Rust البيئي أصغر من Java أو Go، إلا أن لدينا بالفعل العديد من المكتبات الناضجة لإدخال الفوضى.



الأداة الغرض الحالة
tokio-rs/bytes محاكاة تأخيرات الشبكة نشط
fault-injection إدخال حالات الذعر والأخطاء مستقر
simulation محاكاة أعطال القرص/الشبكة تجريبي
chaostoolkit إطار عمل لسيناريوهات الفوضى دعم عبر HTTP API


سنركز على مثال عملي باستخدام fault-injection ومحاكاة مشاكل الشبكة.



مثال عملي: "إطفاء الحريق" في خدمة Rust



لنفترض أن لدينا خادم HTTP بسيطًا على axum يقوم بشيء ما (مثل الاتصال بـ API خارجي). نريد التحقق من سلوكه إذا أصبحت الخدمة الخارجية غير متاحة أو بدأت في الاستجابة بتأخير.



الخطوة 1: خادم أساسي به "ثغرة"



لنكتب خادمًا يقوم بطلب إلى httpbin.org (محاكاة لخدمة خارجية):



use axum::{Router, routing::get, response::Json};use reqwest::Client;use std::sync::Arc;use serde_json::Value;

#[tokio::main]async fn main() { let client = Arc::new(Client::new());

let app = Router::new() .route("/fetch", get(handler)) .with_state(client);

axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap();}

async fn handler(client: Arc<Client>) -> Result<Json<Value>, (StatusCode, String)> { let resp = client.get("https://httpbin.org/uuid") .timeout(std::time::Duration::from_secs(5)) .send() .await .map_err(|e| (StatusCode::SERVICE_UNAVAILABLE, e.to_stri

المدونات

توصيات الكتب