خدماتي المصغرة كانت تتحدث بلغات مختلفة: كيف أنقذتني ‘بوابة الواجهات البرمجية’ (API Gateway) من جحيم الفوضى؟

يا جماعة الخير، السلام عليكم ورحمة الله وبركاته. معكم أخوكم أبو عمر.

قبل كم سنة، كنت شغال على مشروع كبير، تطبيق تجارة إلكترونية ضخم. قررنا وقتها، بكل حماس الشباب، نستخدم معمارية الخدمات المصغرة (Microservices). قلنا يا عمي هاي هي المستقبل، كل خدمة قائمة بذاتها، فريق يشتغل عليها، تحديثات سهلة، وما حدا إله علاقة بالتاني. قسمنا الشغل: خدمة للمستخدمين (Users Service)، خدمة للمنتجات (Products Service)، خدمة للطلبات (Orders Service)، وخدمة للإشعارات (Notifications Service). الوضع كان “عال العال” في البداية.

لكن المصيبة بلشت لما إجا فريق الواجهة الأمامية (Frontend) وفريق تطبيق الموبايل بدهم يشبكوا مع هاي الخدمات. أذكر جيدًا يوم دخل عليّ “أحمد”، قائد فريق الواجهة الأمامية، وشعره منكوش وعيونه حمرا. قال لي: “يا أبو عمر، مشان الله الحقني! خدمة المستخدمين بدها توثيق بـ JWT، وخدمة الطلبات بدها API Key، وكل وحدة على رابط شكل (endpoint)، وبس بدي أجيب معلومات طلب واحد للمستخدم، لازم أعمل 3 طلبات مختلفة! واحد يجيب معلومات المستخدم، وواحد يجيب الطلب، وواحد يجيب تفاصيل المنتجات اللي في الطلب. المستخدم بكون كبس على الزر وراح عمل فنجان قهوة ورجع والصفحة لسا بتحمّل!”.

وقتها حسيت إنه الحماس اللي بدينا فيه تحول لكابوس. خدماتنا المصغرة صارت زي جزر معزولة، كل جزيرة بتتكلم لغة مختلفة، والزبون (الواجهة الأمامية) هو المترجم المسكين اللي بده يرضي الكل. كانت فوضى حقيقية… لحد ما لقينا البطل المنقذ اللي لمّ الشمل ورتّب الأمور. وهون يا جماعة الخير، دخل على الخط البطل المنقذ: بوابة الواجهات البرمجية أو الـ API Gateway.

ما هي بوابة الواجهات البرمجية (API Gateway)؟

ببساطة شديدة، تخيل إنك داخل على مبنى شركة ضخم فيه 50 قسم. هل من المنطق إنك تحفظ رقم تلفون كل قسم وتعرف في أي طابق هو؟ أكيد لأ. الحل إنك تتصل على موظف الاستقبال (Receptionist)، وهو بوخذ طلبك وبوصلك بالقسم الصح.

الـ API Gateway هي تمامًا موظف الاستقبال هذا في عالم البرمجيات. هي عبارة عن خادم (Server) يمثل نقطة الدخول الوحيدة لجميع الطلبات القادمة من العملاء (Clients) مثل تطبيقات الويب أو الموبايل. بدل ما العميل يتواصل مباشرة مع عشرات الخدمات المصغرة، هو بيتواصل فقط مع البوابة، والبوابة هي اللي بتتولى مهمة توجيه الطلب للخدمة أو الخدمات الصحيحة في الخلفية (Backend).

رسم توضيحي للفرق بين وجود API Gateway وعدم وجوده

كيف كانت الفوضى قبل الـ API Gateway؟

قبل ما نطبق البوابة، كنا عايشين في جحيم تقني. المشاكل كانت كثيرة ومتشعبة، وأهمها:

1. تعدد نقاط الدخول (Multiple Endpoints)

العميل (تطبيق الموبايل مثلاً) كان لازم يعرف عنوان URL لكل خدمة مصغرة. لو عنا 10 خدمات، لازم يحفظ 10 عناوين. وإذا قررنا نغير عنوان خدمة أو ندمج خدمتين، لازم نحدّث كل تطبيقات العملاء. شغلانة ما بتخلص!

مثال على الفوضى:

  • للحصول على بيانات المستخدم: https://users.my-app.com/api/v1/users/123
  • للحصول على طلباته: https://orders.my-app.com/api/v3/user/123/orders
  • للحصول على إشعاراته: https://notifications.my-app.com/ws (هنا نستخدم WebSocket!)

2. المصادقة والترخيص المبعثرة (Scattered Authentication)

هاي كانت من أكبر المصايب. كل خدمة كان لها منطق مصادقة (Authentication) وترخيص (Authorization) خاص فيها. فريق الواجهة الأمامية كان لازم يتعامل مع أنواع مختلفة من التوكنز (Tokens) والجلسات (Sessions)، وهذا عبء كبير وغير آمن بالمرة. كل خدمة بتحتاج تكتب نفس الكود للتحقق من المستخدم وصلاحياته.

3. “الثرثرة” المفرطة بين العميل والخادم (Chatty API)

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

4. صعوبة المراقبة والتسجيل (Logging & Monitoring)

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

كيف أنقذتنا بوابة الواجهات البرمجية (الفوائد العملية)

لما طبقنا الـ API Gateway، حسينا كأنه “إجا الفرج”. كل المشاكل اللي فوق انحلت أو صارت أسهل بكثير. البوابة صارت هي الواجهة الأمامية لكل خدماتنا، وأعطتنا مجموعة من القوى الخارقة:

1. توحيد نقطة الدخول والتوجيه (Single Entry Point & Routing)

صار عنا عنوان واحد فقط لكل العملاء، مثلاً https://api.my-app.com. العميل ببعت طلبه لهالعنوان، والبوابة بتقرر لأي خدمة مصغرة توجّهه بناءً على المسار (path).

مثلاً:

  • الطلب GET /users/123 يروح على خدمة المستخدمين.
  • الطلب GET /orders/456 يروح على خدمة الطلبات.

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

2. المصادقة والترخيص المركزي (Centralized Authentication)

هاي كانت أكبر راحة نفسية. كل منطق التحقق من هوية المستخدم وصلاحياته صار موجود في مكان واحد: الـ API Gateway.

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

نصيحة من أبو عمر: اجعل خدماتك المصغرة الداخلية (Internal Services) غير متاحة للوصول من الإنترنت العام. ضعها داخل شبكة خاصة (Private Network / VPC)، وفقط الـ API Gateway هو اللي مسموح له يتواصل معها. هذا يضيف طبقة أمان ضخمة.

3. تجميع الطلبات (Request Aggregation)

لمشكلة “الثرثرة”، البوابة قدمت لنا الحل السحري: تجميع الطلبات. بدل ما تطبيق الموبايل يبعت 3 طلبات عشان يعرض صفحة تفاصيل الطلب، صار يبعت طلب واحد فقط للبوابة:

GET /aggregated/order-details/456

والبوابة في الخلفية هي اللي بتقوم بالعمل الشاق:

  1. بتبعت طلب لخدمة الطلبات عشان تجيب تفاصيل الطلب.
  2. بتبعت طلب لخدمة المستخدمين عشان تجيب اسم المستخدم وعنوانه.
  3. بتبعت طلب لخدمة المنتجات عشان تجيب صور وأسماء المنتجات في الطلب.

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

4. تفريغ المهام المشتركة (Offloading Cross-Cutting Concerns)

البوابة صارت هي المكان اللي بنحط فيه كل الشغلات المشتركة بين الخدمات، مثل:

  • تحديد معدل الطلبات (Rate Limiting): عشان نحمي خدماتنا من هجمات الحرمان من الخدمة (DoS) أو الاستخدام المفرط، بنحدد في البوابة إنه كل مستخدم مسموح له مثلاً بـ 100 طلب في الدقيقة.
  • التخزين المؤقت (Caching): بعض الردود اللي ما بتتغير كثير (مثل قائمة فئات المنتجات) ممكن نخزنها في ذاكرة البوابة المؤقتة عشان نرجعها بسرعة بدون ما نرهق الخدمات الداخلية.
  • التسجيل والمراقبة (Logging & Monitoring): كل طلب بمر من البوابة بيتم تسجيله. صار عنا مكان واحد نشوف منه كل حركة المرور في النظام.
  • تحويل البروتوكولات (Protocol Translation): البوابة بتقدر تستقبل طلب HTTP/REST عادي من العميل، وتحوله لطلب gRPC أو تتواصل مع خدمة بتستخدم WebSockets في الخلفية. العميل ما بيعرف أي شي عن التعقيد الداخلي.

مثال عملي: بناء API Gateway بسيطة باستخدام Express.js

عشان الصورة توضح أكثر، خلينا نعمل مثال بسيط جدًا باستخدام Node.js ومكتبة express. رح نبني بوابة بتوجه الطلبات لخدمتين وهميتين.

أولاً، تأكد من تنصيب المكتبات اللازمة:

npm install express http-proxy-middleware morgan

الآن، لنفترض أن لدينا خدمتين تعملان محليًا:

  • خدمة المستخدمين: على http://localhost:3001
  • خدمة المنتجات: على http://localhost:3002

هذا هو كود الـ API Gateway (ملف gateway.js):


const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const morgan = require('morgan');

const app = express();
const PORT = 8000;

// Middleware للتسجيل (Logging)
app.use(morgan('dev'));

// Middleware بسيط للمصادقة (Authentication)
const authMiddleware = (req, res, next) => {
    // في الواقع، هنا يتم التحقق من التوكن (JWT) أو الـ API Key
    // للتبسيط، سنتحقق فقط من وجود هيدر معين
    if (req.headers['x-auth-token'] === 'super-secret-token') {
        console.log('تم التحقق من المستخدم بنجاح!');
        next(); // اسمح للطلب بالمرور
    } else {
        res.status(401).send('غير مصرح لك بالوصول (Unauthorized)');
    }
};

// تطبيق middleware المصادقة على كل المسارات التي تحتاج حماية
app.use('/api', authMiddleware);

// توجيه الطلبات (Routing)
// أي طلب يبدأ بـ /api/users سيتم توجيهه لخدمة المستخدمين
app.use('/api/users', createProxyMiddleware({ 
    target: 'http://localhost:3001',
    changeOrigin: true,
    pathRewrite: {
        '^/api/users': '', // إزالة /api/users من بداية المسار
    },
}));

// أي طلب يبدأ بـ /api/products سيتم توجيهه لخدمة المنتجات
app.use('/api/products', createProxyMiddleware({ 
    target: 'http://localhost:3002',
    changeOrigin: true,
    pathRewrite: {
        '^/api/products': '', // إزالة /api/products من بداية المسار
    },
}));

app.listen(PORT, () => {
    console.log(`API Gateway شغّالة على المنفذ ${PORT}`);
});

الآن، لو العميل أراد الحصول على المستخدم رقم 5، بدل ما يطلب http://localhost:3001/5، سيقوم بطلب:

GET http://localhost:8000/api/users/5

مع إضافة الهيدر x-auth-token: super-secret-token.

البوابة ستتولى التحقق من الهيدر، وإذا كان صحيحًا، ستقوم بتوجيه الطلب إلى http://localhost:3001/5 وتُرجع لك النتيجة. العميل لا يعلم بوجود خدمة المستخدمين على المنفذ 3001 أبدًا!

الخلاصة: البوابة هي حارس العمارة! 🚪

زي ما حكينا، الـ API Gateway هي “حارس العمارة” في مدينة الخدمات المصغرة. هي التي تنظم الدخول والخروج، وتتأكد من هوية الزوار، وتوجههم للمكان الصحيح، وتحافظ على النظام والأمان. بدونها، تتحول المدينة إلى فوضى عارمة.

فوائدها باختصار:

  • تبسيط العميل: نقطة دخول واحدة، لا داعي لمعرفة تفاصيل الخدمات الداخلية.
  • 🔐 أمان مركزي: مكان واحد للمصادقة، تحديد المعدل، والحماية.
  • 🚀 أداء أفضل: من خلال تجميع الطلبات والتخزين المؤقت.
  • 📊 مراقبة أفضل: سجلات مركزية لكل حركة المرور في النظام.
  • 🏗️ مرونة: سهولة في إعادة هيكلة الخدمات الداخلية دون التأثير على العملاء.

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

والله ولي التوفيق.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

برمجة وقواعد بيانات

تطبيقي كان يغرق في بحر الاستعلامات: كيف أنقذني ‘التحميل المسبق’ (Eager Loading) من جحيم N+1؟

تذكرون ذلك اليوم الذي كاد فيه تطبيقي أن ينهار تحت وطأة الاستعلامات البطيئة؟ في هذه المقالة، أشارككم قصة حقيقية وكيف كانت تقنية التحميل المسبق (Eager...

31 مارس، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

مقابلتي التقنية كانت صمتاً مطبقاً: كيف أنقذتني ‘تقنية التفكير بصوت عالٍ’ من جحيم الرفض المحتوم؟

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

31 مارس، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

قاعدة بياناتي كانت على وشك الانهيار: كيف أنقذتني ‘استراتيجيات التخزين المؤقت’ (Caching) من جحيم الاستعلامات المتكررة؟

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

31 مارس، 2026 قراءة المزيد
أتمتة العمليات

عمليات النشر كانت كابوساً: كيف أنقذتني ‘خطوط أنابيب CI/CD’ من جحيم أعطال ما بعد الإطلاق؟

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

31 مارس، 2026 قراءة المزيد
البودكاست