نشر Canary باستخدام Rust: دليل خطوة بخطوة مع أمثلة الكود

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

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

ابدأ الدورة

نشر Canary باستخدام Rust: بلا خوف ولا تردد

\n\n

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

\n\n

ولكن هناك طريقة لجعل النشر شبه خالٍ من الألم: نشر Canary (النشر التجريبي). الفكرة بسيطة: تقوم بتوجيه الكود الجديد ليس لجميع المستخدمين دفعة واحدة، بل لنسبة صغيرة (على سبيل المثال، 5-10%). إذا كان كل شيء على ما يرام، تزيد النسبة تدريجيًا. إذا لم يكن الأمر كذلك، تسترجع الإصدار، ولا يعلم بذلك سوى حفنة من "الكناري".

\n\n

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

\n\n

لماذا Rust مثالي لنشر Canary؟

\n\n

Rust ليست مجرد لغة أخرى. ميزاتها تجعل النشر التجريبي فعالاً بشكل خاص:

\n\n
    \n
  • أمان الذاكرة — تضمن Rust عدم تسرب الذاكرة أو سباقات البيانات (data races) إلى الإنتاج. أخطاء أقل = فرصة أقل لفشل الكناري.
  • \n
  • حجم ثنائي صغير — cargo build --release ينتج ملفًا تنفيذيًا مضغوطًا. يمكن نسخه بسرعة إلى عدة خوادم أو حاويات.
  • \n
  • أداء عالٍ — تعمل Rust بمستوى C/C++. هذا يعني أن خادم الكناري الخاص بك لن يتراجع تحت الحمل، حتى لو تم توجيه 10% من حركة المرور إليه.
  • \n
  • النظام البيئي — مكتبات مثل actix-web و tokio و tower توفر أدوات جاهزة لـ HTTP والموازنة والمقاييس.
  • \n
\n\n

النتيجة: خدمة Rust مستقرة وسريعة وسهلة الإدارة الدقيقة لحركة المرور. مثالية لنشر Canary!

\n\n

هندسة نشر Canary باستخدام Rust

\n\n

لنفترض أن لدينا خدمة ويب مبنية على actix-web. API REST عادي: يستقبل الطلبات، ويكتب في قاعدة البيانات، ويعيد الردود. نريد تحديث الإصدار من v1 إلى v2، ولكن ليس دفعة واحدة.

\n\n

المخطط الأساسي:

\n\n
    \n
  1. موازن التحميل (مثل Nginx أو HAProxy) يوزع حركة المرور بين الإصدارات.
  2. \n
  3. المجموعة الرئيسية (المستقرة) — خوادم v1، تستقبل 90% من الطلبات.
  4. \n
  5. مجموعة Canary — خادم أو خادمان مع v2، يستقبلان 10% من الطلبات.
  6. \n
  7. المراقبة — نجمع المقاييس من كلا المجموعتين: الأخطاء، زمن الاستجابة، عدد الطلبات في الثانية.
  8. \n
\n\n

عندما نتأكد من أن v2 يعمل بشكل مستقر، نزيد وزن مجموعة Canary تدريجيًا حتى 100%.

\n\n

الخطوة 1: كتابة خادم Rust مع المقاييس

\n\n

سيقوم خادمنا بتقديم إصدارين من نقطة النهاية /api/hello. للتبسيط، يختلف الإصداران في سلسلة الرد. في مشروع حقيقي، قد يكون هذا منطق عمل مختلفًا.

\n\n
// Cargo.toml\n[dependencies]\nactix-web = "4"\nactix-rt = "2"\nserde = { version = "1", features = ["derive"] }\nprometheus = { version = "0.13", features = ["process"] }\nlog = "0.4"\nenv_logger = "0.10"
\n\n

الآن الخادم نفسه. سنضيف مقاييس Prometheus لمراقبة صحة الكناري:

\n\n
use actix_web::{web, App, HttpServer, HttpResponse, middleware::Logger};\nuse prometheus::{Counter, HistogramVec, register_counter, register_histogram_vec};\nuse std::sync::OnceLock;\n\n// المقاييس العامة\nstatic REQUEST_COUNT: OnceLock<Counter> = OnceLock::new();\nstatic REQUEST_DURATION: OnceLock<HistogramVec> = OnceLock::new();\n\nfn init_metrics() {\n    REQUEST_COUNT.get_or_init(|| {\n        register_counter!(\n            "http_requests_total",\n            "Total number of HTTP requests"\n        ).unwrap()\n    });\n    REQUEST_DURATION.get_or_init(|| {\n        register_histogram_vec!(\n            "http_reques                

المدونات

توصيات الكتب