اختبار تجاوز الفشل: هل تنجو تدفقة TCP قائمة؟
قد يقبل المخرج الاحتياطي كل اتصال جديد ومع ذلك يقطع النقل الجاري. اختبر النتيجتين، واحتفظ بحالة العودة إلى الأساسي داخل الخطة.
تختبئ نتيجتان داخل جملة «النسخة الاحتياطية تعمل». طلب جديد ينجح، وهذا هو الاسترداد. ونقل جارٍ بالفعل يستمر، وهذه هي الاستمرارية. هذان وعدان مختلفان، ومعظم تصاميم تجاوز الفشل تفي بالأول بينما ينتهي الثاني بهدوء بانتهاء المهلة. قرّر أيّهما تحتاج قبل اختيار الآلية، واكتب الاختبار بحيث يميّز بينهما.
نتيجتان تبدوان كنجاح واحد
تخيّل عميلاً على العنوان 10.90.0.42 لديه اتصال إلى 198.51.100.20:443. يحوّل المخرج الأساسي ذلك إلى عنوان عام ومنفذ واحد، ويحوّله المخرج الاحتياطي إلى آخر. عنوان العميل الداخلي لا يتغيّر أبداً، ولهذا يتوقّع الناس أن ينجو الاتصال.
لا يرى الخادم عنواناً داخلياً. إنه يرى نقطة النهاية المحوّلة، وهذه النقطة مختلفة بعد التبديل.
لذلك تنتهي التدفقة القديمة بانتهاء المهلة بينما يعمل اتصال جديد إلى الخدمة نفسها فوراً. كلتا الملاحظتين صحيحتان في الوقت نفسه.
ما يراه الخادم عندما يتغيّر المخرج
يُعرَّف اتصال TCP برباعيته، وتغيير عنوان المصدر أو منفذه ينشئ اتصالاً مختلفاً بالنسبة للمضيف المتلقّي. الحزم التي تصل من مصدر جديد على اتصال لا يعرفه الخادم تُسقَط أو يُردّ عليها بإعادة تعيين. ولا شيء في عنوان عميل VPN يحفظ الارتباط عبر هذا التغيير.
يوجد تجاوز الفشل ذو الحالة تحديداً لتجنّب ذلك، وهو يعمل بتبادل حالة التحويل وحالة الاتصال بين أجهزة التمرير. هذه ميزة في الزوج لا في النفق، ويجب تصميمها واختبارها بدل افتراضها.
تحقّق مما إذا كان الزوج يحتفظ بالحالة فعلاً قبل أن تعد أحداً بالاستمرارية. تعرض الأوامر أدناه الحالة الحالية على الجانبين.
conntrack -L -d 198.51.100.20 2>/dev/null | head
ss -tin dst 198.51.100.20
tcpdump -ni any host 198.51.100.20 -c 10لماذا لا يكفي العنوان العام نفسه
الاحتفاظ بعنوان عام واحد عبر المسارين بداية جيدة، لأن الخادم يرى عندها نقطة المصدر نفسها. لكنه لا يكفي وحده. لا يزال جهاز التمرير يحتاج حالة التحويل وحالة الجدار الناري ومسار عودة صالحاً، ويجب أن توجد هذه على الجهاز الذي يحمل الحركة بعد التبديل.
يصف RFC 3022 تحويل العناوين ويعامل تبادل الحالة بين أجهزة التحويل كجزء من تصميم احتياطي. العنوان العائم أو الملف الشخصي المنسوخ ينقل الإعداد دون نقل الحالة.
لهذا فإن اختباراً يكتفي بالـ ping عبر النسخة الاحتياطية يثبت القليل جداً. فـ ping ليس لديه حالة اتصال يخسرها.
قرّر مدى قوة المتطلب
إذا كان بإمكان المستخدمين إعادة الاتصال بعد فشل، فالتصميم تصميم استرداد واختبار القبول هو طلب جديد. وإذا كان يجب أن ينجو نقل ملف، فيحتاج التصميم إلى مزامنة الحالة واختبار أكثر حرصاً بكثير. وإذا كان يجب أن تنجو جلسة بعيدة، فالمتطلب أقوى مرة أخرى وقد يحتاج آلية على مستوى التطبيق بدل آلية على مستوى الشبكة.
اكتب المتطلب جملةً ذات نتيجة قابلة للقياس، مثل أن يكتمل الرفع دون إعادة بدء أو أن يعيد المشغّل الاتصال خلال دقيقة. ثم اختر أرخص آلية تحققه، وهي غالباً تصميم الاسترداد.
قل صراحةً ما يحدث عندما يعود الأساسي، لأن العودة التلقائية قد تقطع اتصالاً كان قد تعافى للتو على النسخة الاحتياطية. تلك الحالة تنتمي إلى خطة الاختبار لا إلى حاشية.
افحص التدفقة القديمة والطلب الجديد
ابدأ نقلاً طويل الأمد غير ضار عبر الأساسي، ثم طلباً جديداً منفصلاً إلى الخدمة نفسها. سجّل سياق التطبيق وعنوان المخرج الملاحَظ والوقت. اقطع الأساسي بطريقة معتمدة وواصل مراقبة النقل الأصلي أثناء إرسال الطلب الجديد عبر النسخة الاحتياطية.
أبلغ عن ثلاث قيم: هل استمرت التدفقة القديمة أم أُعيد تعيينها أم انتهت بانتهاء المهلة، ومتى نجحت العملية الجديدة أول مرة، وهل قطعت العودة إلى الأساسي شيئاً. تلك الأسطر الثلاثة هي سجل القبول.
ss -tin dst 198.51.100.20
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://198.51.100.20/
tcpdump -ni any port 443 -c 20إذا كانت وحدة العمل تكتب بيانات، فلا تكرّر عملية غير مؤكدة بشكل أعمى بعد انتهاء المهلة. فقد تكون الكتابة قد وصلت قبل أن يضيع الجواب. اسأل التطبيق عن النتيجة، أو أعد المحاولة فقط حيث تكون العملية عُدْمية الأثر. ثم اكتب بيان القبول في ثلاثة أجزاء: العمليات الجديدة تتعافى وفق سياسة المخرج، والتدفقات القائمة لها سلوك الانقطاع الموثّق، والتطبيق يستأنف بأمان. ذلك البيان قابل للاختبار، وهو صادق بشأن ما لا يَعِده التصميم.