نشر Canary باستخدام TypeScript: إصدار سلس دون خوف من تعطيل الإنتاج

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

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

ابدأ الدورة

مقدمة: لماذا لا تزال تخشى الضغط على "Deploy"؟

\n\n

لقد كتبت الكود. اختبرته على جهازك المحلي. اجتازت الاختبارات. كل شيء مثالي. تضغط على الزر المرغوب Deploy... وبعد 5 دقائق ترى خطأ 500 يظهر، والمستخدمون في ذعر يكتبون للدعم. هل هذا مألوف؟

\n\n

استراتيجيات النشر التقليدية (blue-green, rolling update) جيدة، لكن لديها عيب واحد: إما أنها تشمل كل الكود الجديد مرة واحدة، أو لا تشمله على الإطلاق. ماذا لو كان بإمكانك إرسال ميزة جديدة إلى 1% فقط من المستخدمين، ومشاهدة المقاييس، وبعد ذلك فقط، بعد التأكد من الاستقرار، إطلاقها على 100%؟

\n\n

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

\n\n

في هذه المقالة، سنكتب باستخدام TypeScript نظامًا كاملاً لنشر Canary. ستتعلم كيفية إعداد موازنة حركة المرور، وكيفية أتمتة العملية عبر CI/CD، وكيفية مراقبة "صحة" الكناري الخاص بك. هيا بنا!

\n\n

ما هو نشر Canary ولماذا هو مطلوب؟

\n\n

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

\n\n

المزايا الرئيسية:

\n
    \n
  • تقليل المخاطر - تؤثر الأخطاء على جزء صغير فقط من الجمهور.
  • \n
  • التراجع السريع - يكفي إعادة توجيه حركة المرور مرة أخرى إلى النسخة المستقرة.
  • \n
  • اختبار A/B في ظروف حقيقية - يمكن مقارنة مقاييس النسخة القديمة والجديدة.
  • \n
  • الطرح التدريجي - لا تقتل الخادم بارتفاع مفاجئ في الحمل.
  • \n
\n\n

الآن دعنا ننتقل من النظرية إلى التطبيق. سنقوم ببناء نظام يتكون من ثلاثة أجزاء:

\n
    \n
  1. الخلفية باستخدام TypeScript (Express.js).
  2. \n
  3. موازن حركة المرور باستخدام Nginx.
  4. \n
  5. الأتمتة عبر GitHub Actions.
  6. \n
\n\n

الخطوة 1. كتابة تطبيق باستخدام TypeScript مع دعم الإصدارات

\n\n

أولاً، سننشئ تطبيق Express بسيطًا يمكنه العمل في وضعين: stable و canary. سيكون الاختلاف فقط في الاستجابة لنقطة النهاية الجذرية، ولكن في مشروع حقيقي، يمكن أن تكون هذه أي ميزة جديدة.

\n\n
// src/app.ts\nimport express, { Request, Response } from 'express';\nimport dotenv from 'dotenv';\n\ndotenv.config();\n\nconst app = express();\nconst PORT = process.env.PORT || 3000;\nconst VERSION = process.env.VERSION || 'stable'; // 'stable' أو 'canary'\n\napp.get('/', (req: Request, res: Response) => {\n  res.json({\n    message: 'Hello from API!',\n    version: VERSION,\n    timestamp: new Date().toISOString(),\n  });\n});\n\n// نقطة نهاية للتحقق من الصحة\napp.get('/health', (req: Request, res: Response) => {\n  res.status(200).send('OK');\n});\n\napp.listen(PORT, () => {\n  console.log(`Server running on port ${PORT} in ${VERSION} mode`);\n});\n
\n\n

الآن سننشئ Dockerfile لتعبئة التطبيق في حاوية. هذا سيسهل النشر والموازنة.

\n\n
# Dockerfile\nFROM node:18-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\nFROM node:18-alpine AS runner\nWORK                

المدونات

توصيات الكتب