نمط التين الخانق: طريقة آمنة لترحيل التطبيقات المتجانسة

نمط التين الخانق: طريقة آمنة لترحيل التطبيقات المتجانسة

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

عندما تقرر الفرق تحديث أنظمتها من خلال الانتقال إلى الخدمات الصغيرة، فإنها تواجه سؤالاً بالغ الأهمية: كيف نعيد كتابة النظام دون الإضرار بأعمالنا الحالية؟

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

لحسن الحظ، هناك بديل أكثر أمانًا وموثوقية: نمط التين الخانق. في هذا الدليل، سوف نستكشف ما هو نمط Strangler Fig Pattern، ولماذا يعمل، وكيفية تطبيقه خطوة بخطوة باستخدام الرسوم البيانية الواضحة والتعليمات البرمجية الواقعية.


تشبيه العالم الحقيقي: نبات التين الخانق

تمت تسمية هذا النمط على اسم التين الخانق، وهو نبات موطنه الغابات الاستوائية المطيرة.

تنبت بذور التين الخانق في الفروع العلوية لشجرة “مضيفة” موجودة. فبدلاً من النمو من الأرض إلى الأعلى، تنمو شجرة التين إلى الأسفل:

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

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


لماذا تفشل إعادة كتابة “الانفجار الكبير”.

قبل الغوص في آليات نمط Strangler Fig، دعونا نفهم لماذا البديل - إعادة الكتابة الكاملة - خطير للغاية:

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

كيف يعمل نمط التين الخانق

الفكرة الأساسية لنمط الشكل الخانق هي الترحيل المتزايد. بدلاً من ترحيل النظام بأكمله، يمكنك ترحيل ميزة صغيرة واحدة أو “شريحة” واحدة في كل مرة.

مخطط مراحل هجرة نمط التين الخانق

يتم تنفيذ عملية الترحيل في خمس مراحل رئيسية:

1. تحديد السياق المحدود

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

  • الميزات التي تتغير بشكل متكرر (وبالتالي يستفيد الفريق بسرعة من عمليات النشر المستقلة).
  • ميزات بسيطة ومنخفضة المخاطر (مثل الأسئلة الشائعة الثابتة أو قسم تفضيلات المستخدم) لاختبار مسار الترحيل.
  • ميزات ذات حدود قاعدة بيانات نظيفة ومحددة جيدًا.

2. تنفيذ الخدمة المصغرة الجديدة

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

3. تقديم طبقة الاعتراض

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

في البداية، تقوم البوابة بتوجيه 100% من كافة الطلبات إلى الوحدة القديمة.

4. تحويل حركة المرور بشكل متزايد

بمجرد اختبار الخدمة الصغيرة الجديدة بالكامل وجاهزيتها، يمكنك تحديث قواعد التوجيه في طبقة الاعتراض. بدلاً من توجيه طلبات الميزة التي تم ترحيلها (على سبيل المثال، /api/users) إلى الوحدة المتراصة، تقوم البوابة بإعادة توجيهها إلى الخدمة الصغيرة الجديدة.

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

5. الخروج من الخدمة والتكرار

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

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


طبقة الاعتراض: مثال على التوجيه السريع

قلب نمط Strangler Fig هو طبقة الاعتراض. يسمح لك بإعادة توجيه الطلبات دون تعديل تطبيقات العميل (تطبيقات الويب، تطبيقات الهاتف المحمول).

فيما يلي مثال عملي لـ Node.js باستخدام وكيل بوابة يعتمد على Express. يقوم بتوجيه الطلبات ديناميكيًا: تنتقل الطلبات الواردة إلى الخدمات الجديدة إذا كانت تطابق المسارات المُرحَّلة؛ وإلا فإنهم سيعودون إلى الكتلة القديمة.

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const PORT = 8080;

// Configuration: Target server URLs
const LEGACY_MONOLITH_URL = 'http://legacy-monolith-server:3000';
const NEW_USER_SERVICE_URL = 'http://new-user-service:3001';
const NEW_PAYMENT_SERVICE_URL = 'http://new-payment-service:3002';

// Simple logging middleware to track traffic distribution
app.use((req, res, next) => {
    console.log(`[ROUTE LOG] Incoming request: ${req.method} ${req.url}`);
    next();
});

// 1. MIGRATED: User registration & profile requests route to the new microservice
app.use('/api/users', createProxyMiddleware({
    target: NEW_USER_SERVICE_URL,
    changeOrigin: true,
    pathRewrite: {
        '^/api/users': '/v1/users', // Translate path format if necessary
    }
}));

// 2. MIGRATED: Payment transactions route to the new payment microservice
app.use('/api/payments', createProxyMiddleware({
    target: NEW_PAYMENT_SERVICE_URL,
    changeOrigin: true
}));

// 3. FALLBACK: All other legacy routes automatically default to the Monolith
app.use('/', createProxyMiddleware({
    target: LEGACY_MONOLITH_URL,
    changeOrigin: true
}));

app.listen(PORT, () => {
    console.log(`Interception Gateway routing traffic successfully on port ${PORT}`);
});

التعامل مع قاعدة البيانات: الجزء الأصعب

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

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

  1. الكتابة المزدوجة: تقوم طبقة الاعتراض أو التطبيق بكتابة البيانات إلى كل من قاعدة البيانات القديمة وقاعدة بيانات الخدمة الجديدة في وقت واحد أثناء مرحلة النقل. وهذا يحافظ على مزامنة قاعدتي البيانات.
  2. تغيير التقاط البيانات (CDC): أداة مثل Debezium تراقب سجل معاملات قاعدة البيانات القديمة وتقوم تلقائيًا بدفق التغييرات إلى قاعدة بيانات الخدمات الصغيرة الجديدة في الوقت الفعلي تقريبًا.

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


المقارنة: إعادة كتابة الانفجار الكبير مقابل شكل سترانجلر

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

خاتمة

يعد Strangler Fig Pattern هو المعيار الصناعي لترحيل الوحدات المتراصة إلى الخدمات الصغيرة. من خلال استبدال التعليمات البرمجية القديمة بشكل متزايد بدلاً من استبدالها مرة واحدة، فإنك تقضي على خطر حدوث “الانفجار الكبير”.

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

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


استكشف المزيد من الرؤى المتعلقة بتطوير البرامج وهندسة الواجهة الخلفية على مدونة Gaznix →