نشر Canary في JavaScript: إصدارات آمنة بدون خوف

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

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

ابدأ الدورة

نشر Canary مع JavaScript: كيف تطلق التحديثات دون خوف من تعطيل كل شيء

\n\n

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

\n\n

الاسم مستوحى من ممارسة قديمة لعمال المناجم، حيث كانوا يأخذون طيور الكناري معهم إلى المنجم. إذا صمت الطائر، فهذا يعني أن الهواء مسموم ويجب الخروج فورًا. في عالم تطوير JavaScript، المبدأ نفسه: نوجه أولاً نسبة صغيرة من المستخدمين إلى الإصدار الجديد، ونراقب "صحة" النظام، ثم نطلق الإصدار الكامل.

\n\n

في هذه المقالة، سنشرح كيفية تنفيذ نشر Canary باستخدام JavaScript الخالص (وقليل من Node.js). بدون أدوات مؤسسية معقدة - فقط كود ومنطق وفطرة سليمة.

\n\n

لماذا Canary وليس Blue-Green أو Rolling Update؟

\n\n

هناك عدة استراتيجيات للنشر. Blue-Green تعني وجود بيئتين متطابقتين، وتقوم ببساطة بتحويل حركة المرور بينهما. Rolling Update هو استبدال تدريجي للحاويات في Kubernetes. لكن Canary لديه قوة خارقة: اختبار A/B حقيقي على مستخدمين حقيقيين.

\n\n
    \n
  • مخاطر أقل: إذا كان الإصدار الجديد "يقتل" قاعدة البيانات، سيتأثر 1% فقط من المستخدمين، وليس 100%.
  • \n
  • ردود فعل سريعة: ترى مقاييس الكود الجديد قبل أن يصل إلى الجميع.
  • \n
  • تراجع تلقائي: إذا زادت الأخطاء، يتم إيقاف Canary تلقائيًا.
  • \n
\n\n

معمارية نشر Canary في JavaScript

\n\n

تخيل أن لدينا تطبيق Express يقدم صفحات HTML. نريد إطلاق تصميم جديد للصفحة الرئيسية. بدلاً من تغيير المسار (Router) للجميع، سننشئ طبقة وسيطة - Canary Middleware.

\n\n

مكونات النظام

\n
    \n
  • Feature Flag - علامة تقوم بتشغيل الإصدار الجديد لمجموعة معينة.
  • \n
  • موزع حركة المرور - منطق يقرر: هل نعرض الإصدار القديم (v1) أم الجديد (v2).
  • \n
  • المراقبة - جمع المقاييس (الأخطاء، زمن الاستجابة، معدلات التحويل).
  • \n
  • التراجع التلقائي - إذا انخفضت المقاييس عن الحد المطلوب.
  • \n
\n\n

مثال بسيط باستخدام Node.js و Express

\n\n

لنبدأ بخادم أساسي. لنفترض أن لدينا معالجين: v1 (قديم) و v2 (جديد).

\n\n
const express = require('express');\nconst app = express();\nconst PORT = 3000;\n\n// الإصدار القديم\napp.get('/api/v1/home', (req, res) => {\n  res.json({ version: 'v1', message: 'التصميم القديم الجيد' });\n});\n\n// الإصدار الجديد (Canary)\napp.get('/api/v2/home', (req, res) => {\n  res.json({ version: 'v2', message: 'تصميم جديد ومذهل!' });\n});\n\napp.listen(PORT, () => console.log(`الخادم يعمل على المنفذ ${PORT}`));\n
\n\n

الآن نحتاج إلى تحديد من سيشاهد v2. الطريقة الأسهل هي الاختيار العشوائي بناءً على معرف المستخدم.

\n\n

توزيع حركة المرور: عشوائية حتمية

\n\n

لا نريد أن يتنقل نفس المستخدم بين الإصدارات مع كل طلب. لذلك نستخدم تجزئة (Hash) لمعرف المستخدم:

\n\n
function getCanaryGroup(userId, percentage = 5) {\n  // تجزئة بسيطة: مجموع رموز الأحرف\n  const hash = userId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);\n  return (hash % 100) < percentage;\n}\n\n// مثال على الاستخدام\nconsole.log(getCanaryGroup('user_123')); // true أو false\n
\n\n

الآن في Middleware نتحقق مما إذا كان المستخدم ضمن مجموعة Canary:

\n\n
app.use('/api/home', (req, res, next) => {\n  const userId = req.headers['x-user-id'] || 'مجهول';\n  \n  if (getCanaryGroup(userId, 5)) { // 5% من حركة المرور\n    req.url = '/api/v2/home';\n  } else {\n    req.url = '/api/v1/home';\n  }\n  next();\n});\n
\n\n

بهذه الطريقة، يمكنك البدء في اختبار إصداراتك الجديدة بأمان تام!

المدونات

توصيات الكتب