تواجه كل فريق هندسي في النهاية نفس الواقع المرعب: حيث يصبح النظام الأحادي القديم عنق زجاجة يعيق الابتكار. الشفرة البرمجية متشابكة، ودورات النشر بطيئة، وإضافة ميزات جديدة تبدو وكأنها تفجير قنبلة. لسنوات، كان النصيحة القياسية هي إعادة الكتابة الكاملة—"Big Bang"—ببناء نظام جديد من الصفر وتبديل المفتاح. ومع ذلك، فإن هذا النهج يحمل مخاطر هائلة وغالباً ما يفشل بسبب تجاوز التكاليف وتأخر الجدول الزمني.
هنا يأتي دور نمط شجرة التين القاتل (Strangler Fig Pattern)، وهي استراتيجية هجرة صاغها مارتن فاولر. تماماً كما تنمو شجرة التين القاتل حول شجرة مضيفة، وتمتصها تدريجياً حتى تموت الشجرة المضيفة، يتضمن هذا النمط استبدال أجزاء من النظام القديم تدريجياً بخدمات مصغرة جديدة. اليوم، سنستكشف كيفية تنفيذ هذا النمط بفعالية، وإدارة توجيه حركة المرور، وضمان عدم وجود توقف عن العمل أثناء الانتقال.
لماذا يهم الانتقال التدريجي
الميزة الأساسية لنمط شجرة التين القاتل هي التخفيف من المخاطر. من خلال نقل الوظائف قطعة تلو الأخرى، يمكنك التحقق من صحة كل خدمة جديدة بشكل مستقل. إذا فشلت خدمة جديدة، يمكنك ببساطة إعادة توجيه حركة المرور مرة أخرى إلى النظام القديم دون التأثير على بقية التطبيق. يسمح هذا النهج التكراري للفريقين بتقديم القيمة باستمرار بدلاً من انتظار تاريخ "اكتمال" افتراضي بعد سنوات.
المكونات الأساسية للاستراتيجية
للتنفيذ الناجح للنمط، تحتاج إلى نهج استراتيجي لتوجيه حركة المرور. الآلية الأكثر شيوعاً هي بوابة API (API Gateway) أو طبقة وسيطة (Proxy) تقع أمام كل من النظام الأحادي القديم والخدمات المصغرة الجديدة. تعمل هذه البوابة كضابط مرور، وتقرر ما إذا كان الطلب يجب أن يتم معالجته بواسطة النظام القديم أم الخدمة الحديثة الجديدة.
لنلقِ نظرة على تنفيذ عملي باستخدام مثال Node.js/Express. في هذا السيناريو، نقوم باستخراج خدمة مصادقة المستخدم من نظام أحادي أكبر.
تنفيذ منطق البوابة
تحتاج البوابة إلى آلية لتوجيه الطلبات بناءً على مسارات URL أو معايير محددة. فيما يلي مثال مبسط لكيفية ظهور منطق التوجيه هذا في دالة وسيطة (Middleware).
const express = require('express');
const app = express();
// تكوين لعلماء الميزات أو قواعد التوجيه
const STRANGLER_CONFIG = {
'/api/users': 'new_microservice',
'/api/orders': 'legacy_monolith' // لا يزال في النظام الأحادي
};
// وسيطة لاعتراض الطلبات
app.use((req, res, next) => {
const path = req.path;
const target = STRANGLER_CONFIG[path];
if (target === 'new_microservice') {
console.log(`Routing ${req.method} ${path} to new microservice`);
// توجيه الطلب إلى عنوان URL للخدمة المصغرة الجديدة
proxyService(req, res, 'http://localhost:3001');
} else if (target === 'legacy_monolith') {
console.log(`Routing ${req.method} ${path} to legacy monolith`);
// توجيه الطلب إلى عنوان URL للنظام الأحادي القديم
proxyService(req, res, 'http://localhost:8080');
} else {
// الهروب الافتراضي
next();
}
});
function proxyService(req, res, targetUrl) {
// منطق وسيط مبسط للعرض التوضيحي
// في الإنتاج، استخدم مكتبات مثل http-proxy أو nginx
const http = require('http');
const options = {
hostname: new URL(targetUrl).hostname,
port: new URL(targetUrl).port,
path: req.url,
method: req.method,
headers: req.headers
};
const proxyReq = http.request(options, (proxyRes) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers);
proxyRes.pipe(res, { end: true });
});
req.pipe(proxyReq, { end: true });
}
اعتبارات رئيسية للنجاح
بينما يوضح الكود أعلاه آلية التوجيه، فإن الانتقال الناجح يتطلب أكثر من مجرد تقسيم حركة المرور. يجب عليك إدارة اتساق البيانات بعناية. غالباً ما يكون للخدمة المصغرة الجديدة قاعدة بيانات خاصة بها، مما يتطلب مزامنة مع قاعدة بيانات النظام القديم خلال فترة الانتقال. يمكن أن تساعد أدوات مثل تكرار قاعدة البيانات أو CDC (التقاط تغيير البيانات) في الحفاظ على مزامنة هذه المتاجر البيانات.
بالإضافة إلى ذلك، تأكد من أن أدوات المراقبة والرصد الخاصة بك تغطي كل من الأنظمة القديمة والجديدة. يصبح تتبع الطلبات الموزعة أمراً ضرورياً عندما قد يمتد طلب مستخدم واحد عبر وحدة قديمة وخدمة مصغرة جديدة.
الخاتمة
نمط شجرة التين القاتل ليس حلاً سحرياً، لكنه أحد أكثر الاستراتيجيات فعالية لتحديث البنى التحتية المعقدة والأحادية. إنه يغير التركيز من إعادة الكتابة عالية المخاطر وعالية العواقب إلى سلسلة من مهام إعادة الهيكلة القابلة للإدارة ومنخفضة المخاطر. من خلال اختناق النظام القديم تدريجياً، تحافظ على استمرارية الأعمال بينما تتحرك بثبات نحو مستقبل قابل للتوسع وقابل للصيانة.
ابدأ صغيراً. حدد سياقاً محدداً متماسكاً واحداً داخل نظامك الأحادي، وابنِ خدمة جديدة له، وقم بتوجيه حركة المرور من خلال بوابة. مع اكتساب الثقة، قم بتوسيع محيط بنيتك الجديدة حتى يصبح النظام القديم مجرد ذكرى. إن رحلة التحديث هي ماراثون وليست سباقاً سريعاً—دع شجرة التين القاتل تقود الطريق.