النشر مقابل الإصدار: لماذا لا يصل كودك الجديد إلى المستخدمين بعد؟

لقد انتهيت للتو من عملية النشر. خط الأنابيب (Pipeline) أخضر، القطعة البرمجية (Artifact) موجودة على خادم الإنتاج، وفريقك مستعد لإعلان انتهاء المهمة. ولكن عندما تتفقد التطبيق، يرى المستخدمون النسخة القديمة. لم يتغير شيء من جهتهم.

هذه اللحظة تربك الكثير من الفرق. لقد فعلت كل شيء بشكل صحيح. الكود موجود. الخادم يشغل الملف الثنائي الجديد. فلماذا لا يحصل المستخدمون على التحديث؟

الإجابة بسيطة: النشر (Deployment) والإصدار (Release) شيئان مختلفان. وفهم هذا الفرق يغير طريقة تفكيرك في توصيل البرمجيات.

النشر يعني أن الكود موجود على الخادم

النشر هو عملية وضع نسخة جديدة من تطبيقك على خادم. تخرج القطعة البرمجية من سجل الحزم (Registry)، وتُنسخ إلى البيئة المستهدفة، ويبدأ الخادم في تشغيلها. إذا قمت بالنشر إلى الإنتاج، فإن النسخة الجديدة موجودة فعليًا على خوادم الإنتاج.

هذا كل شيء. النشر هو إجراء تقني. لا يخبرنا بأي شيء عما إذا كان المستخدمون يمكنهم استخدام النسخة الجديدة أم لا.

فكر في الأمر بهذه الطريقة: لقد قمت بتحميل فيلم جديد على جهاز العرض في السينما. الفيلم مُجهز، والبكرات جاهزة، وجهاز العرض قيد التشغيل. لكن الفيلم لم يبدأ بعد. الجمهور لا يزال يشاهد الفيلم السابق.

الرسم البياني التالي يوضح الخط الزمني وتدفق الحركة بين النسخة القديمة والجديدة أثناء النشر والإصدار والإصدار التدريجي (Canary):

sequenceDiagram participant Dev as Dev Team participant LB as Load Balancer participant Old as Old Version participant New as New Version participant User as Users Dev->>LB: Deploy new version LB->>New: Start new version Note over New: Running but idle User->>LB: Request LB->>Old: Route to old version Note over LB: Release moment Dev->>LB: Switch traffic to new LB->>New: Route all users Note over LB: Canary release Dev->>LB: Route 5% to new User->>LB: Request LB->>New: Route some users LB->>Old: Route most users Dev->>LB: Increase to 50% Dev->>LB: Route 100%

الإصدار يعني أن المستخدمين يحصلون على النسخة الجديدة

الإصدار هو اللحظة التي تبدأ فيها النسخة الجديدة في خدمة حركة المرور الحقيقية للمستخدمين. حركة المرور تعني الطلبات القادمة من المستخدمين إلى تطبيقك. طالما أن حركة المرور لا تزال موجهة إلى النسخة القديمة، فلن يشعر المستخدمون بأي تأثير من الكود الجديد الموجود على الخادم.

النسخة الجديدة موجودة. إنها تعمل. لكنها خاملة. لا أحد يصل إليها.

الإصدار هو عندما تقوم بتحويل اللافتة من "قريبًا" إلى "يُعرض الآن". يبدأ جهاز العرض في الدوران، ويرى الجمهور الفيلم الجديد.

لماذا العناء في فصلهما؟

إذا كان بإمكانك النشر والإصدار في نفس الوقت، فلماذا ترغب في فصلهما؟ لأن الفصل يمنحك التحكم.

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

عندما تفصل بينهما، تحصل على نافذة زمنية. يمكنك:

  • نشر النسخة الجديدة وتركها.
  • مراقبة سلوكها دون تأثير على المستخدمين.
  • التحقق من أنها تبدأ بشكل صحيح، وتتصل بقواعد البيانات، وتتعامل مع الطلبات الداخلية.
  • إصلاح المشكلات قبل أن يلاحظها أي مستخدم.

تلك النافذة هي شبكة الأمان الخاصة بك. تحول النشر من حدث عالي المخاطر إلى عملية روتينية.

كيفية فصل النشر عن الإصدار

الطريقة الأبسط تستخدم موازن التحميل (Load Balancer) أو الخادم الوكيل العكسي (Reverse Proxy). إليك كيفية العمل:

  1. انشر النسخة الجديدة على الخادم بجانب النسخة القديمة.
  2. قم بتكوين موازن التحميل لإرسال كل حركة مرور المستخدمين إلى النسخة القديمة.
  3. تعمل النسخة الجديدة ولكنها لا تتلقى أي طلبات خارجية.
  4. عندما تكون مستعدًا، قم بتحديث تكوين موازن التحميل لتوجيه حركة المرور إلى النسخة الجديدة.

هذا التغيير في التكوين هو الإصدار الخاص بك. يمكن أن يحدث بعد ثوانٍ من النشر، أو بعد ساعات. التوقيت متروك لك.

إليك مثال عملي باستخدام واجهة سطر أوامر (CLI) افتراضية لموازن التحميل لتحويل حركة المرور:

# Deploy new version alongside old version
# (assumes both are already running on the server)

# Check current traffic distribution
trafficctl get-weight myapp
# Output: myapp-v1: 100%, myapp-v2: 0%

# Shift 10% of traffic to the new version (canary)
trafficctl set-weight myapp-v2 10%

# After monitoring, shift all traffic to the new version
trafficctl set-weight myapp-v2 100%

# Rollback if needed: instantly redirect all traffic back to old version
trafficctl set-weight myapp-v1 100%

الإصدارات التدريجية (Canary Releases): الطرح البطيء

النهج الأكثر دقة هو الإصدار التدريجي (Canary Release). بدلاً من تحويل كل حركة المرور مرة واحدة، ترسل أولاً نسبة صغيرة من المستخدمين إلى النسخة الجديدة.

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

هذا النهج يحد من نطاق الضرر (Blast Radius). إذا كان للنسخة الجديدة خطأ، فإن خمسين شخصًا فقط سيواجهونه بدلاً من ألف. تكتشف المشكلات مبكرًا وبأقل ضرر.

تعمل الإصدارات التدريجية بشكل جيد مع أعلام الميزات (Feature Flags) أيضًا. يمكنك نشر كود مخفي خلف علم، وتفعيله لمجموعة صغيرة، ومراقبة النتائج، ثم توسيع الجمهور تدريجيًا.

التراجع دون إعادة نشر

الفصل يسهل أيضًا عملية التراجع (Rollback). إذا أصدرت نسخة سيئة، لا تحتاج إلى إعادة نشر النسخة القديمة. النسخة القديمة لا تزال على الخادم، ولا تزال تعمل، وقادرة على التعامل مع حركة المرور.

كل ما عليك فعله هو تغيير تكوين موازن التحميل مرة أخرى. تتحول حركة المرور إلى النسخة القديمة. يعود المستخدمون إلى أرض مستقرة في غضون ثوانٍ.

قارن ذلك بنهج النشر والإصدار المدمجين. هناك، التراجع يعني:

  • البحث عن القطعة البرمجية القديمة.
  • إعادة نشرها.
  • انتظار إعادة تشغيل الخادم.
  • الأمل في أن عملية التراجع نفسها لا تسبب مشكلات.

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

من يقرر موعد الإصدار؟

النشر هو قرار تقني. يمكن لخط أنابيب CI/CD الخاص بك التعامل معه تلقائيًا. لكن الإصدار غالبًا ما يشمل أصحاب المصلحة من المنتج أو الأعمال.

فريق المنتج يعرف ما إذا كانت الميزة جاهزة للمستخدمين. قد يرغبون في اختبارها داخليًا أولاً، أو إجراء اختبار A/B، أو تأخير الإصدار لأسباب تسويقية. هم يفهمون تأثير المستخدم بطرق لا يستطيع خط أنابيب النشر فهمها.

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

قائمة تحقق عملية لإصدارك القادم

قبل أن تصدر نسخة جديدة للمستخدمين، راجع هذه النقاط:

  • هل تعمل النسخة الجديدة في الإنتاج لبضع دقائق على الأقل دون أخطاء؟
  • هل تظهر السجلات (Logs) سلوكًا طبيعيًا؟
  • هل لديك طريقة لإعادة توجيه حركة المرور إلى النسخة القديمة إذا لزم الأمر؟
  • هل أكد شخص ما أن الميزة جاهزة من منظور المنتج؟
  • هل تم اختيار نافذة الإصدار لتقليل تأثير المستخدم؟
  • هل تعرف من تتصل به إذا حدث خطأ بعد الإصدار؟

هذه القائمة قصيرة عن قصد. تعقيد عملية الإصدار يؤدي إلى تخطي الخطوات. اجعلها بسيطة، وقم بتنفيذها في كل مرة.

الخلاصة الحقيقية

النشر والإصدار ليسا نفس الشيء. النشر هو وضع الكود على الخادم. الإصدار هو السماح للمستخدمين بلمسه. معاملتهما كإجراءين منفصلين يمنحك التحكم في المخاطر، وسرعة التراجع، وتجربة المستخدم.

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