اختبار التحقق من النشر
التحقق من النشر (Deployment verification) هو الاختبار الذي يُجرى على بيئة فور نشر إصدار جديد فيها، للتأكد من أن النشر نجح وأن الإصدار الجديد يتصرف كما هو متوقع مع الإعدادات الحقيقية والبنية التحتية الحقيقية، وفي الإنتاج مع الحركة الحقيقية. الاختبار قبل الإصدار يثبت أن البناء جيد؛ والتحقق من النشر يثبت أن هذا النشر تحديداً جيد. ويفشلان لأسباب مختلفة — متغير بيئة مفقود، أو ترحيل لم يُطبَّق، أو شهادة خاطئة، أو موازن حمل ما زال يشير إلى الإصدار القديم — ولا يظهر أيٌّ من ذلك في تشغيل اختبارات على staging.
يسير هذا الدليل مع العمل بالترتيب الذي يحدث فيه: كتابة خطة التحقق ومعايير التراجع قبل النشر، وتشغيل اختبارات الدخان بعد النشر، وإبقاء الفحوص الاصطناعية عاملة بعده، والتحقق من الإطلاقات التدريجية مثل إصدارات الكناري وأعلام الميزات، وقراءة إشارات المراقبة، والتحقق من التراجع — بما في ذلك ترحيلات قاعدة البيانات التي قد تجعل التراجع صعباً.
ما الذي يغطيه التحقق من النشر
النشر يغيّر أكثر من الكود. إنه يغيّر صور الحاويات والإعدادات والأسرار ومخطط قاعدة البيانات والبنية التحتية والتوجيه، وكثيراً في خطوة واحدة. ويفحص التحقق من النشر نتيجة كل ذلك معاً، في البيئة المستهدفة، بسؤال واحد: هل الإصدار الجديد يعمل، ومُعدّ بشكل صحيح، ويمكن الوصول إليه، ويتصرف على الأقل بجودة الإصدار السابق؟
من المفيد الفصل بين النشر (Deploying) والإصدار (Releasing). النشر يضع الكود الجديد على الخوادم؛ والإصدار يعرّض السلوك الجديد للمستخدمين. وتقنيات مثل إصدارات الكناري والتبديل الأزرق-الأخضر وأعلام الميزات موجودة للفصل بينهما، ليتمكن الفريق من التحقق من النشر بتعرّض قليل للمستخدمين أو دون تعرّض قبل الإصدار. وحزمة الدخان هي نفسها الموصوفة في دليل اختبار الدخان والسلامة والانحدار، موجّهة الآن إلى البيئة المنشورة للتو.
- فحص الإصدار — البيئة تقدّم الإصدار المقصود نشره، على كل مثيل (instance).
- الصحة والاعتماديات — الخدمات تعمل وتستطيع الوصول إلى قواعد بياناتها وطوابيرها وذاكراتها المؤقتة والأطراف الثالثة.
- المسارات الحرجة — تسجيل الدخول والمعاملة التجارية الرئيسية وواجهتها البرمجية تستجيب بشكل صحيح.
- الإعدادات والأمان — عناوين URL والشهادات وإعادات التوجيه وترويسات الأمان صحيحة؛ ولا وضع تصحيح مفعّل.
- السلوك تحت الحركة الحقيقية — الأخطاء وزمن الاستجابة ومقاييس العمل مماثلة للإصدار السابق.
حدّد معايير النجاح والتراجع قبل النشر
أهم جزء من التحقق من النشر يحدث قبل النشر: تدوين شكل «الجيد» وما الذي سيطلق التراجع. المعايير التي تُقرَّر أثناء الحادثة تُقرَّر تحت الضغط، ممن يكون مستيقظاً، مع ميل قوي إلى «لنمنحه خمس دقائق أخرى». أما المعايير المقررة مسبقاً فتحوّل التراجع إلى خطوة روتينية بدلاً من جدال.
تتسع الخطة لصفحة واحدة. تسمّي خطوات الإطلاق، والأشخاص المناوبين، والإشارات والعتبات التي تعرّف النجاح، والشروط التي يتراجع عندها الفريق دون نقاش، وكيف يتم التراجع وكيف سيُتحقق منه. المثال أدناه لخدمة تُنشر كإصدار كناري؛ والعتبات للتوضيح، وينبغي أن تأتي عتباتك من خط الأساس الطبيعي للخدمة.
- الإطلاق والتحضير: كناري 5% ثم 25% ثم 100%، بخمس عشرة دقيقة لكل خطوة، والعلم new_checkout مطفأ عند النشر؛ ومهندس الإصدار ومختبِر مناوب مسمّيان في تذكرة الإصدار؛ وقبل النشر نسخة احتياطية مؤكدة وترحيل 0042 إضافي فقط (خطوة التوسيع). وتعمل حزمة الدخان بعد النشر على الكناري ثم على عنوان الإنتاج.
- إشارات النجاح، مقارنةً بخط الأساس عند كل خطوة: معدل HTTP 5xx لا يزيد على خط الأساس بأكثر من 0.5 نقطة مئوية؛ وزمن استجابة p95 لا يتجاوز 1.2 ضعف خط الأساس؛ ومعدل إتمام الشراء ضمن 10% من خط الأساس في النافذة الزمنية نفسها؛ ولا توقيعات أخطاء جديدة في السجلات.
- معايير التراجع، ويكفي أيٌّ منها للتراجع دون نقاش: إخفاق اختبار الدخان على الكناري أو الإنتاج؛ أو معدل 5xx فوق 2% لخمس دقائق متتالية؛ أو إخفاقات الدفع فوق ضعفي خط الأساس؛ أو تنبيه سلامة بيانات (طلبات مكررة أو مفقودة).
- التراجع والاكتمال: يُعاد نشر الصورة 5.8.3 ويبقى العلم new_checkout مطفأ ويُبقى على الترحيل 0042 لأنه إضافي؛ ويُعدّ التراجع مُتحقَّقاً منه حين ينجح smoke.sh وتُبلغ نقطة النهاية /version عن 5.8.3 على كل مثيل (instance). ولا يكتمل الإطلاق إلا بعد ساعة كاملة على 100% من الحركة وكل الإشارات خضراء.
Release verification plan: orders-service 5.9.0 (example)
Deployment: canary 5% -> 25% -> 100%, 15 min per step; flag new_checkout OFF at deploy
People: release engineer + tester on call (named in the release ticket)
Before: backup confirmed; migration 0042 is additive only (expand step)
Post-deploy smoke: smoke.sh against the canary, then against the production URL
Success signals, canary compared with baseline, at every step:
- HTTP 5xx rate <= baseline + 0.5 percentage points
- p95 latency <= baseline x 1.2
- checkout conversion within 10% of baseline (same window)
- no new error signatures in the logs
Rollback criteria (any one => roll back, no debate):
- smoke failure on canary or production
- 5xx rate above 2% for 5 consecutive minutes
- payment failures above baseline x 2
- data integrity alert (duplicate or missing orders)
Rollback method: redeploy image 5.8.3; new_checkout stays OFF; migration 0042 is kept (additive)
Rollback verified: smoke.sh passes and /version reports 5.8.3 on every instance
Done when: 100% of traffic for 1 hour with all signals green- 1خطة مكتوبة قبل النشرإشارات النجاح ومعايير التراجع ومهندس الإصدار ومختبِر مناوب؛ نسخة احتياطية مؤكدة؛ ترحيل 0042 إضافي فقطقبل النشر
- 2نشر 5.9.0العلم
new_checkoutمطفأ عند النشر - 3اختبار الدخان بعد النشر
smoke.shعلى الكناري ثم على عنوان الإنتاجفرع: إخفاق الدخان في أيهما ← تراجعفشل
- 4كناري 5%خمس عشرة دقيقة
فرع: تحقّق أي معيار للتراجع ← تراجعفشل
بوابة: كل إشارات النجاح خضراء مقارنةً بخط الأساس
- 525% من الحركةخمس عشرة دقيقة
فرع: تحقّق أي معيار للتراجع ← تراجعفشل
بوابة: كل إشارات النجاح خضراء مقارنةً بخط الأساس
- 6100% من الحركةمراقبة ساعةً كاملة بالإشارات نفسها
فرع: تحقّق أي معيار للتراجع ← تراجعفشل
طوال الخطوات 4–6 إشارات النجاح: 5xx لا يزيد على خط الأساس بأكثر من 0.5 نقطة مئوية، p95 لا يتجاوز 1.2 ضعف خط الأساس، معدل إتمام الشراء ضمن 10% من خط الأساس في النافذة الزمنية نفسها، ولا توقيعات أخطاء جديدة
بعد ذلك:اكتمل: ساعة كاملة على 100% من الحركة وكل الإشارات خضراء
- معايير التراجع: أيٌّ منها ← تراجع دون نقاشإخفاق اختبار الدخان؛ أو معدل 5xx فوق 2% لخمس دقائق متتالية؛ أو إخفاقات الدفع فوق ضعفي خط الأساس؛ أو تنبيه سلامة بيانات (طلبات مكررة أو مفقودة)
- التراجع: إعادة نشر الصورة 5.8.3يبقى
new_checkoutمطفأ ويُبقى على الترحيل 0042؛ ويُتحقق منه حين ينجحsmoke.shوتُبلغ نقطة النهاية/versionعن 5.8.3 على كل مثيل
خطة مثال للخدمة orders-service 5.9.0: العتبات للتوضيح، وينبغي أن تأتي عتباتك من خط الأساس الطبيعي لخدمتك.
اختبارات الدخان بعد النشر
شغّل حزمة الدخان كآخر خطوة في مهمة النشر، على البيئة المنشورة للتو، واجعل خط الأنابيب يفشل إن فشلت. أبقِها قصيرة (بضع دقائق)، ومستقلة عن بيانات اختبار قد لا توجد في الإنتاج، وآمنة للتشغيل على الإنتاج: استدعاءات للقراءة فقط، أو كتابات بحساب اختبار مخصص تُستبعد بياناته من التقارير والفوترة. وافحص السلوك السلبي أيضاً — فنقطة النهاية المحمية التي تعيد فجأة 200 دون رمز عيبُ نشر.
السكربت أدناه مثال لأبسط شكل مفيد: فحوص HTTP برموز حالة متوقعة صريحة وفحص للإصدار. وتنقل معظم الفرق لاحقاً الفحوص نفسها إلى إطار اختبار API أو الواجهة لديها لتُنشر النتائج بصيغة التقرير نفسها كبقية الاختبارات.
- استهدف كل نسخة أو منطقة إن استطعت، لا موازن الحمل فقط — فنسخة واحدة قديمة عيب نشر جزئي كلاسيكي.
- تجاوز الذاكرات المؤقتة في فحص واحد على الأقل؛ فشبكة CDN قد تقدّم صفحة مخزّنة تبدو سليمة بينما يعيد الخادم الأصلي أخطاء.
- اجعل نقطة الصحة ذات معنى: ينبغي أن تُبلغ عن حالة الاعتماديات، لا أن تعيد 200 لمجرد أن العملية حية.
- افحص ترويسات الأمان وTLS وإعادات التوجيه بعد تغييرات البنية التحتية؛ فهي تُعدّ خارج الكود ويسهل فقدانها.
#!/usr/bin/env bash
# Example post-deployment smoke script. Usage: ./smoke.sh https://staging.example.com
set -euo pipefail
BASE_URL="$1"
EXPECTED_VERSION="${EXPECTED_VERSION:-}"
check() { # name, path, expected HTTP status
local name="$1" path="$2" expected="$3" status
status=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$BASE_URL$path" || true)
if [ "$status" != "$expected" ]; then
echo "FAIL $name: $path returned $status, expected $expected"
exit 1
fi
echo "ok $name ($status)"
}
check "health" "/health" 200
check "home page" "/" 200
check "product API" "/api/v1/products/1001" 200
check "auth still needed" "/api/v1/orders" 401
# Only if the service exposes its version
if [ -n "$EXPECTED_VERSION" ]; then
deployed=$(curl -s --max-time 10 "$BASE_URL/version" || true)
if [ "$deployed" != "$EXPECTED_VERSION" ]; then
echo "FAIL version: got $deployed, expected $EXPECTED_VERSION"
exit 1
fi
echo "ok version ($deployed)"
fiجرّبها: فاحص صحة API جرّبها: مختبِر نقاط نهاية API جرّبها: محلّل ترويسات الأمان جرّبها: فاحص إعادة التوجيه
الفحوص الاصطناعية بعد النشر
اختبار الدخان يعمل مرة واحدة؛ أما المراقبة الاصطناعية (Synthetic monitoring) فتستمر في العمل. الفحوص الاصطناعية معاملات مكتوبة — تحميل الصفحة الرئيسية، وتسجيل الدخول بحساب مراقبة، والبحث، والإضافة إلى السلة، واستدعاء API أساسية — تُنفّذ وفق جدول من خارج النظام، كل بضع دقائق، مع تنبيهات عند الفشل أو البطء. وهي تلتقط مشكلات تظهر بعد مدة من النشر: تسرّب ذاكرة، أو شهادة تقترب من الانتهاء، أو مهمة مجدولة تكسر ذاكرة مؤقتة، أو طرف ثالث غيّر سلوكه.
عامل الفحوص الاصطناعية كاختبارات: احفظها في نظام إدارة الإصدارات، وراجعها مع كل تغيير في الميزات، وامنحها حسابات وبيانات اختبار مخصصة، وتأكد أن إخفاقها يصل إلى شخص. الفحص الاصطناعي الذي يفشل بصمت منذ أسبوع أسوأ من غيابه، لأنه يوهم بوجود تغطية. وحين تكتب الجدول كتعبير cron، افحصه وافحص أوقات تشغيله التالية قبل الاعتماد عليه.
جرّبها: مولّد تعابير cron جرّبها: شارح تعابير cron جرّبها: محلّل زمن الاستجابة
إصدارات الكناري والنشر الأزرق-الأخضر وأعلام الميزات
التسليم التدريجي (Progressive delivery) يعرّض التغيير لحصة متزايدة من الحركة، مع فحص عند كل خطوة. في إصدار الكناري (Canary release) يتلقى الإصدار الجديد أولاً حصة صغيرة من الحركة — بضعة في المئة، أو المستخدمين الداخليين — ويُقارن سلوكه بخط الأساس الذي يشغّل الإصدار القديم قبل زيادة الحصة. ويصف دليل SRE العملي من Google الكناري بأنه مقارنة مجموعة الكناري بمجموعة ضابطة، وهذه هي النقطة الأساسية للمختبِرين: قارن المتماثل بالمتماثل، في النافذة الزمنية نفسها، لا الكناري بأسطول الأمس كله.
النشر الأزرق-الأخضر (Blue-green deployment) يُبقي بيئتين متطابقتين؛ يُنشر الإصدار الجديد في الخاملة منهما، ويُتحقق منه هناك بحزمة الدخان، ثم تُحوَّل الحركة إليها، مع إبقاء البيئة القديمة جاهزة للعودة الفورية. وأعلام الميزات (Feature flags) تفصل الإصدار عن النشر داخل الكود: السلوك الجديد يُشحن مطفأً، ثم يُفعَّل للمستخدمين الداخليين، ثم لنسبة من العملاء، ويمكن إطفاؤه دون إعادة نشر.
- اختبر حالتي العلم، والانتقال بينهما للمستخدمين في منتصف مسار (سلة أُنشئت والعلم مطفأ، وأُتمّ شراؤها وهو مفعّل).
- تحقق من الاستهداف: العلم مفعّل تماماً للمستخدمين أو المناطق أو النسبة المقصودة، ومطفأ لكل من سواهم.
- شغّل حزمة الدخان على الكناري أو البيئة الخاملة مباشرة، قبل أن تصلها أي حركة حقيقية.
- أبقِ الإصدارين متوافقين أثناء الإطلاق: واجهات API وصيغ الرسائل ومخطط قاعدة البيانات يجب أن تعمل مع الكود القديم والجديد في آن واحد.
- أزل الأعلام بعد الإصدار الكامل؛ فالأعلام طويلة العمر تضاعف التوليفات التي يجب اختبارها.
إشارات المراقبة التي تُتابع
أثناء الإطلاق وبعده يعتمد التحقق على إشارات الإنتاج لا على نتائج الاختبار. والإشارات الذهبية الأربع في كتاب SRE من Google حد أدنى معقول: زمن الاستجابة، والحركة، والأخطاء، والتشبّع. وأضف إشارات العمل، لأن كثيراً من عيوب النشر لا تنتج أي خطأ — الطلبات تتوقف ببساطة، أو المجاميع خاطئة. قارن كل إشارة بخط الأساس للفترة نفسها وابحث عن تغيرات مفاجئة تتزامن مع وقت النشر.
- الأخطاء — معدل HTTP 5xx، والمهام الفاشلة، وأخطاء JavaScript في المتصفح، ورسائل خطأ جديدة لم تكن موجودة قبل النشر.
- زمن الاستجابة — p95 وp99 لنقاط النهاية الأساسية، لا المتوسط فقط؛ فالطلبات الناجحة البطيئة انحدار أيضاً.
- الحركة — الانخفاض المفاجئ قد يعني أن المستخدمين لا يصلون إلى ميزة؛ والارتفاع المفاجئ قد يعني عواصف إعادة المحاولة.
- التشبّع — المعالج والذاكرة ومجمّعات الاتصالات وعمق الطوابير؛ فالتسرّب البطيء يظهر هنا بعد ساعات من اختبار دخان نظيف.
- العمل — التسجيلات وعمليات الدخول والشراء والدفع والرسائل المرسلة، مقارنةً بالساعة نفسها في الأيام السابقة.
- صحة التسليم عبر الزمن — نسبة فشل التغييرات وزمن التعافي من النشر الفاشل، وهما من مقاييس DORA، يُظهران ما إذا كان التحقق من النشر والتراجع يعملان عبر إصدارات كثيرة.
التراجع والتحقق من الإصدار
التراجع (Rollback) نشرٌ بحد ذاته ويجب التحقق منه بالطريقة نفسها: شغّل حزمة الدخان مجدداً وتأكد أن نقطة الإصدار تُبلغ عن الإصدار السابق على كل مثيل. تدرّب على التراجع في staging لأي إصدار يغيّر البنية التحتية أو البيانات، وقِس زمنه — فالتراجع الذي يستغرق ساعة ليس شبكة أمان لعيب يكلّف مالاً كل دقيقة. وأحياناً يكون الإصلاح الأمامي (forward fix) أسرع وأكثر أماناً من التراجع؛ فقرّر أيهما ينطبق في الخطة لا أثناء الحادثة.
ترحيلات قاعدة البيانات هي أكثر ما يجعل التراجع صعباً. فبمجرد أن يحذف الترحيل عموداً أو يعيد تسمية جدول أو يعيد كتابة بيانات، قد لا يعود الإصدار السابق من الكود قادراً على العمل مع المخطط الجديد، وقد يُفقد عكسُ الترحيل بياناتٍ كُتبت منذ النشر. والتخفيف الشائع هو نهج التوسيع ثم التقليص (expand and contract): أضف أولاً البنى الجديدة بطريقة متوافقة مع السابق، وانشر كوداً يعمل مع كلتيهما، وانقل البيانات، ولا تُزِل البنى القديمة إلا في إصدار لاحق. أما اختبار الترحيلات — على نسخة بحجم الإنتاج، ومع الكود القديم مقابل المخطط الجديد، مع قياس الأقفال والمدة — فيغطيه دليل اختبار معاملات قاعدة البيانات وترحيلاتها.
- معايير تراجع مكتوبة قبل النشر، بعتبات رقمية ومالك قرار مسمّى.
- إجراء تراجع مُتدرَّب عليه ومقيس زمنياً؛ ومخرَج الإصدار السابق ما زال متاحاً.
- اختبار الكود القديم مقابل المخطط الجديد كلما شُحن ترحيل مع الإصدار.
- خطوات الترحيل الهدّامة (الحذف وإعادة التسمية وتغيير النوع) تُشحن في إصدار لاحق للكود الذي توقف عن استخدامها.
- التحقق من التراجع بحزمة الدخان وفحص الإصدار نفسيهما المستخدمَين في النشر.
عيوب نشر نموذجية
- الإنتاج يعيد 5.8.3 على نسختين من ست بعد نشر 5.9.0 (إطلاق جزئي).
- نقطة الصحة تعيد 200 بينما مجمّع اتصالات قاعدة البيانات مستنفد.
- اختبار الدخان ينجح على صفحة CDN مخزّنة بينما يعيد الخادم الأصلي 502.
- GET /api/v1/orders يعيد 200 دون رمز بعد تغيير إعدادات البوابة.
- ترويسة Strict-Transport-Security مفقودة على موازن الحمل الجديد.
- الكناري يُظهر ثلاثة أضعاف معدل 5xx في خط الأساس على POST /orders للمستخدمين ذوي البطاقات المحفوظة.
- العلم new_checkout المفعّل لـ 5% يعرض المسار الجديد أيضاً للزوار غير المسجلين.
- التراجع إلى 5.8.3 يفشل: الكود القديم لا يستطيع قراءة الطلبات ذات الحالة الجديدة PENDING_REVIEW.
- فحص تسجيل الدخول الاصطناعي يفشل منذ ستة أيام لأن كلمة مرور حساب الاختبار انتهت صلاحيتها.
قائمة تحقق للتحقق من النشر
- خطة التحقق مكتوبة: خطوات الإطلاق، وإشارات النجاح، ومعايير التراجع، والمالكون.
- الترحيلات مراجَعة للتوافق مع السابق؛ والكود القديم مختبَر مقابل المخطط الجديد.
- حزمة الدخان بعد النشر تعمل آلياً وتُفشل خط الأنابيب عند إخفاقها.
- الإصدار مؤكَّد على كل مثيل أو منطقة.
- ترويسات الأمان وTLS وإعادات التوجيه مفحوصة بعد تغييرات البنية التحتية.
- الكناري أو البيئة الخاملة مُتحقَّق منها قبل الحركة الحقيقية؛ ومقارنة بخط الأساس عند كل خطوة.
- أعلام الميزات مختبَرة في الحالتين وللاستهداف الصحيح.
- الإشارات الذهبية وإشارات العمل متابَعة للمدة المتفق عليها.
- التراجع مُتدرَّب عليه ومقيس زمنياً ومُتحقَّق منه بحزمة الدخان نفسها.
- الفحوص الاصطناعية محدّثة للسلوك الجديد وتنبّه شخصاً حقيقياً.
الأسئلة الشائعة
ما الفرق بين التحقق من النشر واختبار الإصدار؟
اختبار الإصدار، مثل حزمة الانحدار على المرشح للإصدار، يُظهر أن البناء جيد. والتحقق من النشر يُظهر أن هذا النشر تحديداً للبناء يعمل في بيئته المستهدفة، بإعداداتها وبنيتها التحتية وحركتها الحقيقية. وكلاهما لازم، ويلتقطان عيوباً مختلفة.
هل تشغيل اختبارات الدخان في الإنتاج آمن؟
نعم، إن صُمّمت لذلك: فحوص للقراءة فقط حيثما أمكن، وكتابات فقط عبر حسابات اختبار مخصصة تُستبعد بياناتها من التقارير والفوترة والمراسلات. ولا تستخدم أبداً حسابات عملاء حقيقيين ولا تطلق مدفوعات أو رسائل حقيقية.
ما إصدار الكناري؟
نشرٌ يتلقى فيه الإصدار الجديد أولاً حصة صغيرة من الحركة، وتُقارن أخطاؤه وزمن استجابته وإشارات العمل فيه بالإصدار القديم العامل بجانبه. إن كان الكناري سليماً تنمو الحصة خطوة بخطوة؛ وإلا يُتراجع عنه بأثر محدود على المستخدمين.
متى نتراجع بدلاً من الإصلاح الأمامي؟
حين تتحقق معايير التراجع المتفق عليها قبل النشر ويكون التراجع معروفاً بأنه آمن وسريع. وقد يكون الإصلاح الأمامي أفضل حين يكون التراجع معطّلاً، بسبب ترحيل بيانات مثلاً، أو حين يكون الإصلاح صغيراً ويمكن نشره أسرع من التراجع. قرّر أيهما ينطبق في الخطة.
لماذا تجعل ترحيلات قاعدة البيانات التراجع صعباً؟
لأن الكود السابق قد لا يعمل مع المخطط المتغير، ولأن عكس الترحيل قد يُفقد بيانات كُتبت بعد النشر. ونهج التوسيع ثم التقليص يتجنب ذلك بجعل كل تغيير في المخطط متوافقاً مع السابق وإزالة البنى القديمة في إصدار لاحق فقط.
هل الفحوص الاصطناعية بديل عن المراقبة الحقيقية؟
لا. الفحوص الاصطناعية تخبرك ما إذا كانت الرحلات المكتوبة تعمل من الخارج؛ ومراقبة المستخدمين الحقيقيين والسجلات والمقاييس تخبرك بما يحدث للحركة الفعلية. استخدم الاثنين: الفحوص الاصطناعية تلتقط الانقطاعات على مسارات قليلة الحركة، والمراقبة الحقيقية تلتقط مشكلات لا تغطيها سكربتاتك.
المراجع
- Canarying Releases — The Site Reliability Workbookإطلاق التغيير لنسبة صغيرة من الحركة أولاً ومقارنته بخط الأساس قبل التعميم — التحقق من النشر كما يُمارس في هندسة موثوقية المواقع.
- Site Reliability Engineering: How Google Runs Production Systemsأهداف مستوى الخدمة وميزانيات الخطأ ومراقبة «الإشارات الذهبية الأربع» والتعامل مع الحمل الزائد — الجانب التشغيلي للمرونة.
- DORA's software delivery performance metricsمقاييس DORA للتسليم — زمن تنفيذ التغيير وتكرار النشر وزمن التعافي من النشر الفاشل ونسبة فشل التغييرات وما يتصل بها — مجمّعة حسب الإنتاجية وعدم الاستقرار.
- Release It! Second Edition: Design and Deploy Production-Ready Software (Michael T. Nygard)أنماط الاستقرار — المهل الزمنية وقواطع الدائرة والحواجز والضغط العكسي — وأنماط الفشل التي يُفترض أن يكشفها اختبار الحمل.
- Continuous Integration (Martin Fowler)الوصف الأكثر استشهاداً للتكامل المستمر: ادمج كثيراً، واجعل البناء يختبر نفسه وسريعاً، وأصلح البناء المكسور فوراً.
- GitHub Actions documentationكيف تُعرَّف مسارات العمل والمهام والمشغّلات والمخرجات في GitHub Actions — حيث تعمل الاختبارات الآلية عند كل دفع أو طلب دمج.
تمرين عملي
راجع خطة التحقق ثم اقرأ الكناري
أنت المختبِر المناوب في منصة لحجز تذاكر الحافلات عبر الإنترنت (مثال خيالي). يُنشر الإصدار 7.4.0 من خدمة الحجوزات في الإنتاج يوم الخميس كإصدار كناري (Canary release). يضيف الإصدار اختيار المقعد خلف علم ميزة (Feature flag)، ويشحن ترحيلَي قاعدة بيانات، وينقل الخدمة إلى موازن حمل جديد. كتب مهندس الإصدار خطة تحقق من صفحة واحدة وطلب منك مراجعتها قبل النشر. تعرض المادة أدناه قائمة التغييرات، وخط الأساس (Baseline) للخدمة، ومسودة الخطة، ثم في الأسفل قراءة الإشارات من خطوة الكناري الأولى.
اعمل على الورق في جولتين. أولاً صحّح الخطة قبل النشر بأقسام الخطة والدخان والتراجع من الدليل: معايير رقمية مستمدة من خط الأساس، وحزمة دخان تناسب هذا الإصدار، وتراجع يعمل فعلاً. ثم اقرأ قراءة الساعة 10:25 مقابل معاييرك وقرّر ما يحدث بعدها. وتساعدك حاسبة النسب المئوية في حساب العتبات. خصّص لذلك 20–30 دقيقة.
منصة لحجز تذاكر الحافلات عبر الإنترنت (مثال خيالي) - خدمة الحجوزات bookings-service
الإصدار 7.4.0 يحل محل 7.3.2. النشر: الخميس 15 أكتوبر 2026، الساعة 10:00.
البنية: 6 مثيلات (instances) خلف موازن حمل؛ وشبكة CDN أمام صفحات الويب.
الكناري: مثيلان إضافيان يشغّلان 7.4.0 ويتلقيان حصة موزونة من الحركة.
الأشخاص: مهندس الإصدار ومالك قرار التراجع: طارق | المختبِر المناوب: أنت
قائدة الدعم: لمى
ما الذي يتغير في 7.4.0
- اختيار المقعد في صفحة الحجز، خلف علم الميزة seat_map.
مطفأ عند النشر؛ لاحقاً: حسابات الموظفين -> 10% من العملاء -> 100%.
- الترحيل 0131: إضافة عمود يقبل القيمة الفارغة bookings.seat_number.
- الترحيل 0132: إعادة تسمية العمود bookings.status إلى bookings.state
(الإصدار 7.4.0 يقرأ state ويكتبه؛ والإصدار 7.3.2 يقرأ status ويكتبه).
- موازن حمل جديد بشهادة TLS جديدة؛ وإعادة توجيه HTTP -> HTTPS أُعيد إعدادها.
خط الأساس: آخر 14 يوماً، اليوم نفسه من الأسبوع والساعة نفسها، من لوحات المراقبة
معدل HTTP 5xx 0.2%
زمن استجابة p95 لـ POST /api/v2/bookings 480 ms
معدل إتمام الحجز (بدأ -> دُفع) 62%
معدل إخفاق الدفع 1.0%
مسودة خطة التحقق (كتبها طارق لمراجعتك)
الإطلاق: كناري 5% -> 25% -> 100%، 20 دقيقة لكل خطوة
الدخان: تشغيل smoke.sh يدوياً بعد مهمة النشر
(الصحة، الصفحة الرئيسية، API الرحلات، 401 للمصادقة، الإصدار)
النجاح: لا أخطاء خطيرة، والموقع يبدو سريعاً
التراجع: إن بدا الوضع سيئاً، أعد نشر 7.3.2 واعكس الترحيلات
يكتمل عندما: تكون مهمة النشر خضراء
القراءة عند 10:25 - الكناري على 5% منذ 20 دقيقة؛ الترحيل 0131 مطبَّق
اتُّفق في مراجعة الخطة: تأجيل 0132؛ وبناء 7.4.0 هذا ما زال يستخدم status.
الإشارة الكناري 7.4.0 الضابطة 7.3.2
معدل HTTP 5xx 0.2% 0.2%
زمن استجابة p95 لـ POST /api/v2/bookings 610 ms 470 ms
متوسط زمن الاستجابة لـ POST /api/v2/bookings 210 ms 200 ms
معدل إتمام الحجز 41% 61%
معدل إخفاق الدفع 1.0% 0.9%
توقيعات أخطاء جديدة في السجلات لا شيء -
smoke.sh على مثيلات الكناري كله ناجح، الإصدار 7.4.0
تذكرة من لمى عند 10:18: عميل غير مسجّل الدخول يرى خريطة المقاعد في صفحة
الحجز ولا يستطيع المتابعة إلى الدفع.- أعد كتابة إشارات النجاح ومعايير التراجع في المسودة عتباتٍ رقمية مستمدة من خط الأساس، مع طريقة المقارنة (الكناري مقابل المجموعة الضابطة في النافذة الزمنية نفسها) ومالك قرار التراجع.
- صحّح سطر الدخان: أين تعمل حزمة الدخان بعد النشر ومتى، وما الفحوص التي يجب أن تحويها لهذا الإصدار تحديداً، وكيف تُفشل خط الأنابيب.
- راجع الترحيلَين مقابل سطر التراجع: هل يمكن إعادة نشر 7.3.2 بعد تطبيق 0132؟ ما الذي تغيّره في الإصدار أو في طريقة التراجع؟ ثم أعد كتابة سطرَي «التراجع» و«يكتمل عندما».
- اقرأ قراءة الساعة 10:25 مقابل معاييرك: لكل إشارة قل هل تنجح أم لا، واشرح ما يخبرك به متوسط زمن الاستجابة ومعدل 5xx المتساوي وما لا يخبرانك به. وماذا تقول تذكرة الدعم عن العلم؟
- قرّر: الزيادة إلى 25% أم الإبقاء أم التراجع، واكتب ما يحدث بعد ذلك: خطوات التراجع والتحقق منه، وما يُسجَّل، والعيوب التي تُفتح.
إظهار الإجابة النموذجية
مراجعة الخطة: المعايير. عبارتا «لا أخطاء خطيرة» و«الموقع يبدو سريعاً» لا يستطيع أحد فحصهما عند 10:25، فاستبدل بهما أرقاماً مستمدة من خط الأساس واذكر طريقة المقارنة: الكناري مقابل المجموعة الضابطة (Control) التي تشغّل 7.3.2، في نافذة العشرين دقيقة نفسها، عند كل خطوة، لا مقابل أسطول الأمس كله. إشارات النجاح: معدل HTTP 5xx لا يزيد على الضابطة بأكثر من 0.5 نقطة مئوية (0.7% بخط الأساس هذا)؛ وزمن استجابة p95 لـ POST /api/v2/bookings لا يتجاوز 1.2 ضعف الضابطة (576 ms مقابل خط الأساس 480 ms)؛ ومعدل إتمام الحجز لا يقل عن 90% من معدل الضابطة (نحو 56% بخط أساس 62%)؛ ومعدل إخفاق الدفع لا يتجاوز 1.5 ضعف الضابطة؛ ولا توقيعات أخطاء جديدة في السجلات. معايير التراجع، ويكفي أيٌّ منها للتراجع دون نقاش: فشل اختبار الدخان على الكناري أو الإنتاج؛ أو معدل 5xx فوق 2% لخمس دقائق متتالية؛ أو معدل إتمام الحجز أدنى من الضابطة بأكثر من 10% طوال خطوة كاملة؛ أو معدل إخفاق الدفع فوق ضعفي الضابطة؛ أو تنبيه سلامة بيانات (حجوزات مفقودة أو مكررة، أو مقعد بِيع مرتين). وسمِّ الأشخاص: طارق يملك قرار التراجع، وأنت تشغّل حزمة الدخان وتقرأ الإشارات عند كل خطوة، والعتبات مكتوبة في تذكرة الإصدار قبل 10:00. الأرقام بعينها مسألة تقدير؛ أما غير القابل للنقاش فهو أن تكون موجودة، ومستمدة من خط أساس هذه الخدمة، ومتفقاً عليها قبل النشر.
مراجعة الخطة: الدخان. تشغيل smoke.sh يدوياً بعد المهمة يعني أنه قد يُنسى تحت الضغط، وأنه يأتي بعد أن تكون الحركة قد وصلت، وأنه لا يستطيع إفشال خط الأنابيب. اجعل حزمة الدخان آخر خطوة آلية في مهمة النشر، تعمل أولاً على مثيلات الكناري مباشرة (فالفحص عبر موازن الحمل عند 5% يصل في معظمه إلى 7.3.2)، ثم على الإنتاج بعد كل خطوة، وتُفشل المهمة إن فشل أي فحص. ويجب أن تحوي لهذا الإصدار: GET /health يعيد 200 ونقطة الصحة تُبلغ عن اعتمادياتها (قاعدة البيانات ومزوّد الدفع)؛ والصفحة الرئيسية مع تجاوز الذاكرة المؤقتة ليُفحص الخادم الأصلي لا نسخة CDN؛ وواجهة الرحلات (GET /api/v2/trips لمسار يعمل كل يوم) تعيد 200 وقائمة غير فارغة، بدلاً من معرّف رحلة ثابت ربما غادرت رحلته؛ وGET /api/v2/bookings دون رمز يعيد 401، وهو الفحص السلبي الذي يلتقط بوابة توقفت عن فرض المصادقة؛ و/version يعيد 7.4.0 على كل مثيل كناري، وعند 100% على كل مثيل من المثيلات الستة، لا استدعاءً واحداً عبر موازن الحمل؛ ولأن موازن الحمل والشهادة تغيّرا: شهادة TLS صالحة للنطاق، وhttp:// يعيد التوجيه إلى https:// على المسار نفسه بالرمز 301 أو 308، وترويسات الأمان التي كانت على الموازن القديم، ومنها Strict-Transport-Security، موجودة على الجديد. وأضف فحصاً لحالة العلم: والعلم seat_map مطفأ لا تحوي صفحة الحجز خريطة مقاعد، سواء طُلبت دون جلسة أو بحساب الاختبار. والكتابات، إن وُجدت، عبر حساب الاختبار المخصص فقط الذي تُستبعد حجوزاته من التقارير والمدفوعات.
مراجعة الخطة: الترحيلات والتراجع. الترحيل 0131 يضيف عموداً يقبل القيمة الفارغة: إضافي، و7.3.2 يتجاهله، فيبقى في مكانه عند التراجع ولا يحتاج إلى معالجة خاصة. أما الترحيل 0132 فيعيد تسمية bookings.status إلى bookings.state، وهذا يكسر الخطة مرتين. أولاً لا يمكن لأي كناري أن يعمل معه: أثناء الكناري ما زالت الضابطة تشغّل 7.3.2 وتقرأ status، فلحظة تطبيق 0132 يفشل 95% من الحركة؛ وإن لم يُطبَّق 0132 فإن 7.4.0 يقرأ عموداً اسمه state غير موجود. ثانياً عبارة «أعد نشر 7.3.2 واعكس الترحيلات» ليست طريقة تراجع: فإعادة العمود إلى اسمه القديم أثناء حادثة، تحت الحمل، تكسر أي إصدار ما زال يعمل، وهي ترحيل عكسي لم يشغّله أحد قط يُنفَّذ في أسوأ لحظة ممكنة. والحل نهج التوسيع ثم التقليص (Expand and contract): يُعدَّل 7.4.0 ليواصل استخدام status ويُشحن دون 0132؛ وإن كان الاسم الجديد ضرورياً فعلاً، يضيف إصدار لاحق state عموداً جديداً ويكتب في العمودين ويواصل قراءة status، وتنسخ عملية تعبئة (Backfill) القيم الموجودة، ويقرأ الإصدار التالي state، ولا يحذف status إلا إصدار يأتي بعد أن يكون الكود قد توقف عن استخدامه. وقبل أي إصدار يحمل ترحيلاً يُختبر الكود القديم مقابل المخطط الجديد في staging. أعد كتابة السطرين. التراجع: ما دام الكناري دون 100% يُضبط وزن حركته على صفر؛ وعند 100% يُعاد نشر الصورة 7.3.2 على المثيلات الستة كلها؛ ويُبقى على 0131؛ ويبقى seat_map مطفأً؛ وهو مُتدرَّب عليه ومقيس زمنياً في staging بهدف أقل من 10 دقائق؛ ويُعدّ مُتحقَّقاً منه حين تنجح حزمة الدخان وتُبلغ /version عن 7.3.2 على كل مثيل يتلقى حركة. يكتمل عندما: تمر ساعة كاملة على 100% من الحركة وكل إشارات النجاح خضراء والعلم ما زال مطفأً؛ فمهمة النشر الخضراء لا تثبت إلا أن المهمة انتهت. وإطلاق العلم (الموظفون، ثم 10%، ثم 100%) قرار إصدار منفصل بمعاييره وقراءاته الخاصة.
قراءة الإشارات. تحقق أولاً من الضابطة مقابل خط الأساس: 0.2% و470 ms و61% و0.9% قيم طبيعية لهذه الساعة، فالمقارنة صالحة. معدل 5xx 0.2% مقابل 0.2%: ناجح. زمن p95 610 ms مقابل 470 ms: 1.30 ضعف الضابطة، فوق حد 1.2 ضعف أي 564 ms؛ إشارة النجاح لا تتحقق. متوسط زمن الاستجابة 210 مقابل 200 ms كان سينجح، وهذا بالضبط سبب عدم اعتماد المتوسط معياراً: 5% من الطلبات البطيئة لا تحرّك المتوسط إلا قليلاً بينما ينتظر كل عميل منهم. معدل إتمام الحجز 41% مقابل 61%: ثلث الحجوزات ضاع، وهو أدنى بكثير من حد 10% أي 54.9%؛ تحقق معيار تراجع. معدل إخفاق الدفع 1.0% مقابل 0.9%: ضمن 1.5 ضعف الضابطة، ناجح. لا توقيعات أخطاء جديدة: ناجح. ويُظهر معدل 5xx المتساوي والسجلات النظيفة الغرض من إشارات العمل: هذا العيب لا ينتج أي خطأ، فالعملاء يتوقفون ببساطة قبل الدفع. وبالأخطاء وحدها كان الكناري سيُرقّى إلى 25%.
التذكرة. تقول الخطة إن seat_map مطفأ عند النشر للجميع. وعميل غير مسجّل الدخول يرى خريطة المقاعد، أي إن العلم يُقيَّم مفعّلاً على الأقل للجلسات التي لا مستخدم فيها، وهو عيب استهداف من النوع الذي يعدّه الدليل، والسلوك الجديد يصل إلى عملاء حقيقيين على الكناري بينما يقول الإصدار إنه لم يُطلَق. وهو يفسّر انخفاض الإتمام: خريطة المقاعد تسدّ الطريق إلى الدفع. وقد يكون وراء ارتفاع p95 لـ POST /api/v2/bookings أيضاً إن كان مسار كود خريطة المقاعد يعمل في تلك الطلبات، لكن هذه فرضية لتحليل السبب الجذري لا نتيجة. ولم تره حزمة الدخان لأن أياً من فحوصها لا يحمّل صفحة الحجز بجلسة غير مسجّلة؛ وفحص حالة العلم من الخطوة 2 كان سيلتقطه قبل أي حركة.
القرار: التراجع الآن، لا الإبقاء. تحقق معيار تراجع في نهاية الخطوة الأولى، فالجواب المتفق عليه هو التراجع دون نقاش: تعطي طارق، مالك القرار، المعيار الذي تحقق والقراءة، فيعلن التراجع؛ والمعايير المتفق عليها قبل 10:00 هي ما يجعل هذا قراراً روتينياً لا جدالاً. الخطوات: ضبط وزن الكناري على صفر لتعود الحركة كلها إلى المثيلات الستة التي تشغّل 7.3.2، ثم إخراج مثيلَي الكناري من الخدمة؛ والإبقاء على الترحيل 0131؛ وبقاء seat_map مطفأً؛ وتشغيل حزمة الدخان على كل مثيل من الستة والتأكد أن /version تُبلغ عن 7.3.2 عليها كلها وأن لا حركة تصل إلى 7.4.0؛ ومتابعة الإشارات نفسها في العشرين دقيقة التالية والتأكد أن معدل الإتمام عاد إلى نحو 61%. سجّل وقت القرار، والمعيار الذي تحقق، ومن قرّر، وكم استغرق التراجع، فهذا الرقم هو ما وعدت به الخطة. أما الإصلاح الأمامي (Forward fix) فيُناقش بعد التراجع ومع معرفة السبب الجذري، لا بدلاً منه.
العيوب والمتابعة. أعد إنتاج التذكرة في staging على 7.4.0 والعلم مطفأ، دون تسجيل دخول ومع تسجيل الدخول، ليذكر العنوان بدقة من المتأثر. ثم افتح عيبين مع أدلة الكناري مرفقة: العلم seat_map يُقيَّم مفعّلاً للجلسات غير المسجّلة (أو لأي جلسات تُظهرها إعادة الإنتاج)، بخطورة حرج (Critical) لأنه يسدّ مسار الحجز الرئيسي، مع التذكرة والنافذة الزمنية ومعرّفات مثيلات الكناري؛ وزمن p95 لـ POST /api/v2/bookings 1.3 ضعف الضابطة على 7.4.0، مرتبطاً بالأول حتى يُظهر السبب الجذري هل هو العيب نفسه. وقبل المحاولة التالية: يمر الإصلاح باختبار التأكيد (Confirmation testing) في staging، وينضم فحص حالة العلم وفحوص موازن الحمل إلى حزمة الدخان، ويتأكد فحص اصطناعي لمسار الحجز أن لا خريطة مقاعد تظهر والعلم مطفأ، ويصل تنبيهه إلى شخص، ويُعاد الكناري من 5% بالمعايير نفسها. ولاحظ ما سار على ما يرام: عتبات الخطة حوّلت كناري من عشرين دقيقة إلى تراجع روتيني تأثر فيه 5% من العملاء بدلاً منهم جميعاً.
إن اختلفت أرقامك فراجع القواعد لا الأرقام: كل معيار رقمي، ومستمد من خط أساس هذه الخدمة، ويُقارَن فيه الكناري بالضابطة في النافذة نفسها، ومتفق عليه قبل 10:00 مع مالك قرار مسمّى؛ وحزمة الدخان تعمل آلياً ومباشرة على المثيلات، بفحص للإصدار وفحص سلبي والفحوص التي يستلزمها تغيير البنية التحتية في هذا الإصدار؛ والترحيلات الهدّامة لا تُشحن أبداً مع الكود الذي يتوقف عن استخدامها؛ والتراجع يُتحقق منه كما يُتحقق من النشر. وحدّ أشد لزمن الاستجابة أو حدّ مختلف للإتمام مقبول مع سبب؛ أما «يبدو الوضع سيئاً» فغير مقبول.
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.
جزء من مسار تعلم ضمان الجودة
قبل هذا الموضوع
الموضوعات التالية
الأدوات المذكورة في هذا الدليل
افحص عدة نقاط نهاية لصحة API دفعة واحدة واحصل على الحالة وزمن الاستجابة وملخّص نجاح/فشل.
تحقّق سريعاً من إمكانية الوصول إلى نقطة نهاية API: الحالة وزمن الاستجابة والحجم ونوع المحتوى وTLS.
قِس زمن استجابة نقطة نهاية عبر عدة عيّنات: الحد الأدنى والأقصى والمتوسط والوسيط وp95.
قارن استجابتي API (مثل بيئة التجريب مقابل الإنتاج) واحصل على قائمة بكل فرق بنيوي أو في القيم.
تقييم ترويسات أمان HTTP (CSP وHSTS وX-Frame-Options وReferrer-Policy وPermissions-Policy وCOOP/CORP) من ترويسات ملصقة أو عنوان URL عام.
تتبّع سلاسل إعادة التوجيه (301/302/307/308) وعرض كل قفزة وحالتها وعنوان URL النهائي.
أنشئ تعابير cron بصرياً وعاين أوقات التشغيل التالية.
ترجم أي تعبير cron إلى لغة إنجليزية مبسّطة واعرض أوقات التشغيل القادمة.