عندما يجعل التراجع الأمور أسوأ (وماذا تفعل بدلاً من ذلك)

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

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

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

الإشارة الحقيقية للتراجع

تعتمد معظم الفرق على فحوصات الصحة لتقرر ما إذا كان النشر سليمًا. لكن فحوصات الصحة تخبرك فقط إذا كان التطبيق يعمل تقنيًا. إنها لا تخبرك إذا كان التطبيق يفعل الشيء الصحيح.

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

عادةً ما يأتي قرار التراجع من مجموعة من الإشارات:

  • فحوصات الصحة التي تبدأ بالفشل
  • معدلات الأخطاء التي ترتفع
  • تقارير المستخدمين التي تصف سلوكًا لا يتطابق مع التوقعات
  • مقاييس الأعمال التي تنحرف عن الأنماط الطبيعية

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

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

لماذا التطبيقات عديمة الحالة وذات الحالة ليست متشابهة

تعتمد سهولة التراجع بشكل شبه كامل على ما إذا كان تطبيقك يحتفظ بحالة.

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

بالنسبة للتطبيقات ذات الحالة، التراجع لعبة مختلفة. تخيل أن إصدارك الجديد كتب 10,000 سجل إلى قاعدة البيانات بحقل جديد لا يعرفه الإصدار القديم. عندما تتراجع عن التطبيق، يحاول الإصدار القديم قراءة تلك السجلات. يتعطل لأن تنسيق البيانات لا يتطابق مع ما يتوقعه. أو الأسوأ، أن الإصدار الجديد غيّر هيكل جدول قاعدة البيانات. الآن لا يمكن للتطبيق القديم حتى البدء لأن المخطط غير متوافق.

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

  • استعادة قاعدة البيانات إلى نقطة قبل النشر
  • كتابة نصوص ترحيل تعكس تغييرات المخطط
  • قبول أن بعض البيانات ستفقد أو تتلف

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

ثلاث استراتيجيات تعمل بالفعل

تتطلب المواقف المختلفة طرق تراجع مختلفة. إليك ثلاث طرق تستخدمها الفرق عمليًا.

يمكن لشجرة القرار التالية توجيه اختيارك:

flowchart TD A[تم اكتشاف الفشل] --> B{هل التطبيق ذو حالة؟} B -->|لا| C[تراجع أو تحويل حركة المرور] B -->|نعم| D{هل تغير مخطط البيانات؟} D -->|نعم| E{هل يمكن الإصلاح للأمام بسرعة؟} E -->|نعم| F[إصلاح للأمام] E -->|لا| G[قبول وتصحيح] D -->|لا| H{خلل منطقي أم مشكلة أداء؟} H -->|خلل منطقي| I{هل يمكن الإصلاح للأمام بسرعة؟} I -->|نعم| J[إصلاح للأمام] I -->|لا| K[تحويل حركة المرور أو تراجع] H -->|مشكلة أداء| L[تحويل حركة المرور أو تراجع]

الإصلاح للأمام

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

يعمل الإصلاح للأمام بشكل جيد عندما:

  • يكون الخلل معزولاً ويمكن إصلاحه بسرعة
  • يمكن لخط الأنابيب الخاص بك تسليم إصدار جديد في دقائق
  • البيانات التي كتبها الإصدار المعطل قابلة للاسترداد أو يمكن ترحيلها

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

تحويل حركة المرور

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

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

إليك مثال ملموس باستخدام Kubernetes لتحويل حركة المرور إلى الإصدار القديم أثناء نشر كناري:

# تحقق من تقسيم حركة المرور الحالي (بافتراض خدمة مع محددين)
kubectl get virtualservice my-app -o jsonpath='{.spec.http[0].route[*].weight}'

# تحويل 100% من حركة المرور إلى الإصدار القديم (v1)
kubectl patch virtualservice my-app --type='json' -p='[
  {"op": "replace", "path": "/spec/http/0/route/0/weight", "value": 100},
  {"op": "replace", "path": "/spec/http/0/route/1/weight", "value": 0}
]'

# تحقق من التغيير
kubectl get virtualservice my-app -o yaml | grep -A5 "route:"

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

القبول والتصحيح

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

يعمل هذا النهج عندما:

  • المشكلة ليست حرجة (مشكلة عرض بسيطة، خلل غير مانع)
  • البيانات التي كتبها الإصدار الجديد قيّمة وستفقد عند التراجع
  • يمكن للفريق تسليم تصحيح في وقت معقول

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

قائمة تحقق عملية قبل نشرك التالي

قبل أن تنشر، راجع هذه الأسئلة مع فريقك:

  • ما الإشارات التي ستؤدي إلى قرار التراجع؟ (الصحة، الأخطاء، تقارير المستخدمين، مقاييس الأعمال)
  • كم من الوقت سنراقب قبل اتخاذ القرار؟ (5 دقائق، 15 دقيقة، 30 دقيقة)
  • هل يغير هذا النشر مخطط قاعدة البيانات أو تنسيق البيانات؟
  • إذا كان الأمر كذلك، هل لدينا ترحيل عكسي أو خطة استعادة تم اختبارها؟
  • هل الإصدار القديم لا يزال قيد التشغيل وجاهز لقبول حركة المرور؟
  • هل يمكننا الإصلاح للأمام أسرع مما يمكننا التراجع؟

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

الخلاصة

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

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