“صارت القصة زي سوق الحسبة”.. يوم غرقت في فوضى الخدمات المصغرة
يا جماعة الخير، السلام عليكم ورحمة الله. معكم أخوكم أبو عمر.
قبل كم سنة، كنت متحمس جدًا لمشروع جديد، منصة تجارة إلكترونية ضخمة. قررنا كفريق، وبكل ثقة، نستخدم معمارية الخدمات المصغرة أو الـ “Microservices”. الفكرة كانت براقة: كل جزء من النظام (المستخدمين، المنتجات، الطلبات، الدفع) عبارة عن خدمة صغيرة مستقلة، “كل خدمة في قنينة” زي ما بنحكي. فريق يشتغل على خدمة المنتجات، وفريق ثاني على خدمة الدفع، وهكذا. استقلالية، سرعة في التطوير، وقابلية للتوسع لا نهائية. حلم كل مبرمج، صحيح؟
بعد أشهر قليلة، بدأ الحلم يتحول لكابوس. فريق الواجهة الأمامية (Frontend) كان على وشك “يطق” من كثرة الـ Endpoints اللي لازم يتعامل معها. عشان يعرض صفحة المستخدم الرئيسية، كان لازم يبعث طلب لخدمة المستخدمين عشان يجيب معلومات الحساب، وطلب ثاني لخدمة الطلبات عشان يعرض آخر الطلبات، وطلب ثالث لخدمة التوصيات عشان يعرض منتجات مقترحة. صار التطبيق بطيء، والشباب في الواجهة الأمامية بطلوا يلحقوا على التغييرات.
والمصيبة الأكبر كانت الأمان (Security). كل خدمة من خدماتنا كانت تحتاج آلية مصادقة (Authentication) وتحقق من الصلاحيات (Authorization). صرنا نكرر نفس الكود في كل مكان. إذا اكتشفنا ثغرة، لازم نصلحها في 10 أماكن مختلفة! الوضع صار “شوربة”، والفوضى عمت المكان. حسيت حالي واقف بنص سوق الحسبة في نابلس يوم الجمعة، كل واحد بغني على ليلاه، وما في مين ينظم السير. وقتها أدركت إننا بحاجة لشرطي مرور، بحاجة لحارس على باب العمارة ينظم الدخول والخروج. وهنا كانت بداية رحلتي مع المنقذ: الـ API Gateway.
ما هي فوضى الخدمات المصغرة التي أتحدث عنها؟
قبل ما نحكي عن الحل، خلينا نفهم أصل المشكلة. معمارية الخدمات المصغرة، بالرغم من قوتها، إلا أنها تأتي مع تحدياتها الخاصة إذا لم يتم التعامل معها بحذر. هذه بعض المشاكل التي واجهتنا والتي يواجهها الكثيرون:
- تعقيد العميل (Client Complexity): تطبيق العميل (سواء كان ويب أو موبايل) يصبح مسؤولاً عن معرفة عنوان كل خدمة مصغرة والتواصل معها بشكل مباشر. هذا يضيف عبئًا كبيرًا على فريق الواجهة الأمامية ويجعل الكود معقدًا وهشًا.
- تكرار منطق المصادقة والترخيص: كما ذكرت، تطبيق آليات الأمان في كل خدمة على حدة هو مضيعة للوقت والجهد، ويفتح الباب أمام الأخطاء والثغرات الأمنية.
- الاهتمامات المشتركة (Cross-Cutting Concerns): أمور مثل تسجيل الأنشطة (Logging)، تحديد معدل الطلبات (Rate Limiting)، والتخزين المؤقت (Caching) يجب تطبيقها بشكل مركزي، وتكرارها في كل خدمة يعتبر مخالفة لمبدأ “لا تكرر نفسك” (DRY – Don’t Repeat Yourself).
- تعدد البروتوكولات: قد تستخدم خدمة بروتوكول REST API، بينما تستخدم أخرى gRPC أو GraphQL. العميل سيضطر للتعامل مع كل هذه البروتوكولات المختلفة، مما يزيد من تعقيده.
شرطي المرور المنقذ: ما هو الـ API Gateway؟
ببساطة شديدة، الـ API Gateway هو طبقة وسيطة تقع بين تطبيقات العميل (Frontend/Mobile) ومجموعة الخدمات المصغرة (Microservices). إنه بمثابة نقطة دخول موحدة (Single Point of Entry) لجميع الطلبات القادمة من الخارج.
تخيله مثل موظف الاستقبال في شركة كبيرة. بدلًا من أن يذهب الزائر ويتوه بين المكاتب بحثًا عن الموظف المطلوب، يذهب أولًا إلى الاستقبال. موظف الاستقبال يتحقق من هويته، يعرف من يريد أن يقابل، ثم يوجهه إلى المكتب الصحيح. هذا بالضبط ما يفعله الـ API Gateway.
كيف يعمل الـ API Gateway؟
عندما يرسل تطبيق العميل طلبًا، فإنه لا يرسله مباشرة إلى خدمة المنتجات أو خدمة الطلبات. بل يرسله إلى عنوان واحد فقط: عنوان الـ API Gateway.
- العميل يرسل طلبًا واحدًا إلى
https://api.my-app.com/v1/products. - الـ API Gateway يستقبل هذا الطلب.
- يقوم بالتحقق من صلاحيات الطلب (هل المستخدم مسجل دخوله؟ هل يملك الصلاحية للوصول لهذا المورد؟).
- بناءً على مسار الطلب (
/v1/products)، يعرف الـ Gateway أن هذا الطلب يجب أن يذهب إلى “خدمة المنتجات” التي تعمل على عنوان داخلي مثلhttp://products-service:8080/. - يوجه الـ Gateway الطلب إلى الخدمة الصحيحة.
- تستجيب الخدمة المصغرة، ويعود الرد إلى الـ Gateway.
- يقوم الـ Gateway بإعادة الرد النهائي إلى العميل.
بهذه الطريقة، يصبح العميل غبيًا (وهذا شيء جيد!)، فهو لا يعرف شيئًا عن التعقيدات الداخلية للنظام. كل ما يعرفه هو نقطة دخول واحدة يتحدث معها.
القوى الخارقة للـ API Gateway
الـ API Gateway ليس مجرد موجه للطلبات، بل يمتلك مجموعة من “القوى الخارقة” التي حولت الفوضى في مشروعنا إلى نظام متكامل. إليك أهمها:
1. التوجيه المركزي (Centralized Routing)
هذه هي الوظيفة الأساسية. الـ Gateway يقوم بربط المسارات العامة (Public Routes) بالخدمات الداخلية. هذا يعني أنه يمكننا تغيير أماكن خدماتنا الداخلية أو إعادة هيكلتها دون أن يتأثر تطبيق العميل على الإطلاق.
مثال على إعداد التوجيه (بصيغة YAML شبيهة بما تجده في Kong أو Tyk):
# api-gateway-routes.yaml
routes:
- path: /api/v1/users/
method: GET
destination: http://user-service:3000/
- path: /api/v1/products/
method: [GET, POST]
destination: http://product-service:4000/
- path: /api/v1/orders/
method: ALL
destination: http://order-service:5000/
هذا الإعداد البسيط يخبر الـ Gateway بكيفية توجيه الطلبات بناءً على المسار ونوع الطلب.
2. المصادقة والترخيص (Authentication & Authorization)
هذه كانت أكبر مشكلة حلتها لنا البوابة. بدلًا من تكرار كود التحقق من الـ JWT (JSON Web Tokens) في كل خدمة، أصبح الـ API Gateway هو المسؤول الوحيد عن هذه المهمة. يقوم بالتحقق من التوكن، وإذا كان صالحًا، يمرر الطلب إلى الخدمة الداخلية، وأحيانًا يضيف معلومات المستخدم (مثل User ID) في الـ Headers الخاصة بالطلب. الخدمات الداخلية أصبحت تثق بأن أي طلب يصلها من الـ Gateway هو طلب موثوق.
نصيحة من أبو عمر: لا تثق أبدًا بأي طلب يصل إلى خدماتك الداخلية مباشرة. قم بإعداد شبكتك بحيث لا يمكن الوصول للخدمات المصغرة إلا من خلال الـ API Gateway. افترض دائمًا أن البوابة هي الحارس الوحيد، وأي طلب يتجاوزها هو دخيل يجب منعه.
3. تحديد معدل الطلبات (Rate Limiting)
لحماية خدماتنا من الاستخدام المفرط أو هجمات الحرمان من الخدمة (Denial of Service)، قمنا بتطبيق Rate Limiting على مستوى الـ Gateway. يمكننا بسهولة تحديد أن المستخدم العادي لا يمكنه إرسال أكثر من 100 طلب في الدقيقة، بينما المستخدم ذو الاشتراك المدفوع يمكنه إرسال 1000 طلب. كل هذا يتم في مكان واحد.
4. تجميع الطلبات (Request Aggregation / Fan-out)
هذه الميزة كانت بمثابة السحر لفريق الواجهة الأمامية. بدلًا من أن يرسل تطبيق الموبايل 3 طلبات منفصلة لجلب بيانات صفحة المستخدم، أصبح يرسل طلبًا واحدًا فقط إلى الـ Gateway، مثلاً GET /api/v1/mobile/dashboard.
الـ API Gateway، بدوره، يقوم “بتفريع” هذا الطلب إلى 3 طلبات داخلية:
- طلب إلى
user-serviceلجلب بيانات المستخدم. - طلب إلى
orders-serviceلجلب آخر 5 طلبات. - طلب إلى
recommendations-serviceلجلب المنتجات المقترحة.
ثم ينتظر الرد من جميع الخدمات، يجمع البيانات في كائن JSON واحد، ويرسله كاستجابة واحدة للعميل. هذا يقلل من عدد رحلات الشبكة (Network Roundtrips) ويحسن أداء التطبيق بشكل كبير.
5. التسجيل والمراقبة المركزية (Centralized Logging & Monitoring)
أصبح لدينا مكان واحد نرى فيه جميع الطلبات التي تدخل نظامنا، ومن أين أتت، وكم استغرقت من الوقت، وهل نجحت أم فشلت. هذا سهل علينا كثيرًا عملية اكتشاف الأخطاء ومراقبة أداء النظام ككل.
كيف تختار وتطبق الـ API Gateway؟
الآن بعد أن اقتنعت (أتمنى ذلك) بأهمية الـ API Gateway، السؤال هو: من أين أبدأ؟
جاهز أم بناء مخصص؟ (Buy vs. Build)
هناك خياران رئيسيان:
- حلول جاهزة (Managed/SaaS): مثل AWS API Gateway, Azure API Management, Google Cloud API Gateway. هذه الحلول سهلة الإعداد وتتكفل الشركة المزودة بالصيانة والتحديثات، لكنها قد تكون مكلفة على المدى الطويل.
- حلول مفتوحة المصدر (Open Source): مثل Kong, Tyk, Ocelot (لبيئة .NET), Spring Cloud Gateway (لبيئة Java/Spring). هذه الحلول تمنحك تحكمًا كاملاً ويمكنك استضافتها على خوادمك الخاصة، لكنها تتطلب جهدًا في الإعداد والصيانة.
نصيحة من أبو عمر: للمشاريع الصغيرة والمتوسطة، أو إذا كان فريقك جديدًا على المفهوم، ابدأ بحل جاهز أو مفتوح المصدر شائع. “اللي إلو أول إلو آخر”، والحلول الجاهزة بتوفر عليك وقت وجهد كبير. لا تعيد اختراع العجلة إلا إذا كان لديك متطلبات فريدة جدًا لا يغطيها أي حل آخر.
الخلاصة يا جماعة الخير 🏁
معمارية الخدمات المصغرة هي أداة قوية جدًا، لكن مع القوة تأتي المسؤولية والتعقيد. الـ API Gateway ليس مجرد “إضافة جميلة”، بل هو جزء لا يتجزأ من أي نظام ناجح مبني على هذه المعمارية. إنه شرطي المرور الذي يحول الفوضى إلى نظام، ويوفر طبقة حماية وأداء وتحكم مركزية.
في مشروعنا، الانتقال لاستخدام API Gateway لم يحل المشاكل التقنية فحسب، بل حسن من العلاقة بين فريق الواجهة الأمامية والفرق الخلفية، وزاد من سرعة التطوير، وجعل النظام بأكمله أكثر قوة وأمانًا.
نصيحتي الأخيرة لك: ابدأ ببساطة. لا تحاول تطبيق كل ميزات البوابة من اليوم الأول. ابدأ بوظيفة التوجيه والأمان، ثم أضف الميزات الأخرى تدريجيًا حسب الحاجة. تذكر دائمًا، الهدف هو حل المشاكل، وليس إضافة طبقة جديدة من التعقيد. والله ولي التوفيق. 😉