يا جماعة الخير، السلام عليكم ورحمة الله.
بتذكرها زي كأنها مبارح. كانت ليلة خميس، والساعة داخلة على الوحدة بعد نص الليل. أنا وفريق المطورين الشباب قاعدين بالمكتب، والقهوة بطل إلها مفعول. كان عنا إطلاق لتحديث جديد على التطبيق، وفجأة… كل شي “ضرب”. التطبيق مش راضي يفتح عند المستخدمين، والتقارير بتوصلنا من كل حدب وصوب.
واحد من الشباب الجداد، وجهه أصفر، بقلي: “يا أبو عمر، خدمة المستخدمين (User Service) واقعة!”. رديت عليه وأنا بحاول أفتح عشرين شاشة قدامي: “ماشي يا عمي، اعملها إعادة تشغيل”. شوي وبرجعلي الشب وبقلي: “عملت، بس هسّه خدمة الطلبات (Order Service) مش شايفة خدمة المنتجات (Product Service)!”.
كانت فوضى عارمة. كل خدمة مصغرة (Microservice) الها الـ IP الخاص فيها، وكل وحدة الها طريقة مصادقة مختلفة، واللي ما إلها أصلاً! عشان أشخّص مشكلة بسيطة، كنت مضطر أفتح سجلات (logs) خمس خدمات مختلفة وأحاول أربط الأحداث ببعضها. حسيت حالي مش مبرمج، حسيت حالي محقق جنائي بحاول يحل جريمة معقدة وما معه أي دليل. وقتها صرخت بالشباب: “ولكم يا جماعة! هيك ما بنفع! شغلنا كله صاير مكشوف وفوضوي، لازم نلاقي حل جذري”.
ومن رحم هالمعاناة، انولدت الحاجة لأداة تنظم هذا السيرك… وهاي كانت بداية قصتنا مع بوابة الـ API.
ما هي الفوضى التي كنا نعيشها؟ (مشكلة الخدمات المصغرة المكشوفة)
قبل ما نحكي عن الحل، خلوني أوصفلكم “الجحيم” اللي كنا عايشين فيه، يمكن تلاقوا حالكم بنفس الموقف. لما تبني نظامك على أساس الخدمات المصغرة بدون تخطيط مركزي، رح توقع بهاي المشاكل:
تعدد نقاط الدخول (Multiple Entry Points)
تخيل معي تطبيق الموبايل تبعنا. عشان يعرض صفحة المستخدم الرئيسية، كان لازم يعمل 3 طلبات مختلفة:
- طلب لـ
https://users.myapi.com/profileعشان يجيب معلومات المستخدم. - طلب لـ
https://orders.myapi.com/recentعشان يجيب آخر طلباته. - طلب لـ
https://notifications.myapi.com/unreadعشان يجيب عدد الإشعارات.
فريق الواجهة الأمامية (Frontend) كان بده يطق! أي تغيير بأي خدمة منهم كان معناه تحديث للتطبيق، وكان لازم يديروا بالهم على عناوين مختلفة ومشاكل الشبكة لكل طلب.
كابوس المصادقة والترخيص (Authentication & Authorization Hell)
هاي كانت الكارثة الكبرى. خدمة المستخدمين بتستخدم مصادقة JWT. خدمة المنتجات، لأنها “داخلية” (على أساس!)، ما كان عليها أي مصادقة. خدمة تالتة بتستخدم مفتاح API بسيط. النتيجة؟ ثغرات أمنية بالجملة، وصعوبة بالغة في توحيد صلاحيات المستخدمين. لو بدنا نمنع مستخدم معين من الوصول لجزئية معينة، لازم نعدّل الكود في 3 أماكن مختلفة! شغل مش مرتب بالمرة.
صعوبة المراقبة والتسجيل (Monitoring & Logging Nightmare)
لما مستخدم يشتكي من مشكلة، عملية تتبع طلبه كانت أشبه بالمستحيل. كنا نفتح سجلات خادم الويب، بعدين نروح على سجلات خدمة المستخدمين، وبعدين ننتقل لسجلات خدمة الطلبات… وبالآخر نضيع. ما كان عنا أي رؤية شاملة وموحدة للي بصير بالنظام.
طوق النجاة: تقديم بوابة الـ API (API Gateway)
بعد الليلة المشؤومة هذيك، قررنا إنه “لهون وبس”. الحل كان واضح: لازم يكون عنا نقطة دخول واحدة، حارس واحد مسؤول عن كل من هبّ ودبّ على نظامنا. هذا الحارس هو ما يعرف بـ “بوابة واجهة برمجة التطبيقات” أو الـ API Gateway.
ببساطة يا جماعة، الـ API Gateway هو خادم (Server) بنحطه قدام كل خدماتنا المصغرة. هو بصير الوجه الوحيد اللي بتعامل معه العالم الخارجي (تطبيقات الموبايل، الويب، أي طرف ثالث). هو اللي بستقبل كل الطلبات، وبعدين بقرر لمين يمررها من الخدمات الداخلية.
كيف تعمل البوابة؟ (شرح مبسط)
خلينا نرجع لمثال صفحة المستخدم الرئيسية. مع وجود بوابة API، الموضوع صار هيك:
- تطبيق الموبايل يرسل طلب واحد فقط إلى:
https://api.mycoolapp.com/v1/main-screen. - بوابة الـ API تستقبل هذا الطلب.
- أولاً: تتأكد من هوية المستخدم وصلاحياته (Authentication & Authorization) في مكان واحد مركزي. إذا مش مصرح له، بترجعله خطأ 401 وانتهى الموضوع.
- ثانياً: بعد التأكد من صلاحياته، البوابة “بتفهم” إنه هذا الطلب بحاجة لمعلومات من 3 خدمات مختلفة.
- بتقوم هي، من ورا الكواليس، بإرسال طلبات للخدمات الداخلية (اللي بطل إلها وجود على الإنترنت العام وصارت محمية داخل شبكتنا الخاصة).
- بتجمع الردود من كل الخدمات، وبتدمجهم في رد واحد مرتب ومنسق.
- بترجع هذا الرد الواحد لتطبيق الموبايل.
العميل (تطبيق الموبايل) ما عرف بكل هاي العملية المعقدة. بالنسبة له، هو طلب طلب واحد وجاه رد واحد. شغل نظيف ومُرتب.
الفوائد الجمة التي حصدناها: ليش بوابة الـ API “شغل مرتب”؟
بعد ما طبقنا بوابة الـ API، حسينا حالنا انتقلنا من حمّام السوق لصالون فخم. هاي أهم الفوائد اللي لمسناها مباشرة:
الأمان المركزي (Centralized Security)
كل شي اله علاقة بالأمان صار بمكان واحد:
- المصادقة والترخيص: طبقنا نظام JWT على البوابة نفسها. أي طلب بدون توكن (token) صالح، البوابة بترفضه فوراً قبل ما يوصل لأي خدمة داخلية.
- تحديد معدل الطلبات (Rate Limiting): صرنا نقدر نمنع هجمات الحرمان من الخدمة (DoS) ببساطة عن طريق تحديد عدد الطلبات المسموح فيها لكل مستخدم أو IP في الدقيقة.
- إخفاء البنية التحتية: المهاجم بطل قادر “يشوف” خدماتنا الداخلية ويعرف كيف نظامنا مقسّم. هو بس بشوف البوابة.
تبسيط العميل (Client Simplification)
فريق الواجهة الأمامية صاروا يحبوني زيادة! بدل ما يتعاملوا مع 10 نهايات طرفية (endpoints)، صاروا يتعاملوا مع بوابة واحدة. الكود تبعهم صار أبسط، أسرع، وأسهل للصيانة.
المراقبة والتسجيل الموحد (Centralized Logging & Monitoring)
بما إنه كل الطلبات بتمر من البوابة، صار عنا سجل ذهبي. أي طلب بفشل، بنقدر نشوف مساره كامل من لحظة دخوله للبوابة لحد ما وصل للخدمة اللي سببت المشكلة. ربطناها مع أنظمة مراقبة زي Prometheus و Grafana وصار عنا لوحات تحكم (dashboards) بتفرجينا صحة النظام كاملة بلحظتها.
أمثلة عملية وكود (خلينا نشوف شغل)
الكلام النظري حلو، بس خلينا نشوف مثال عملي. احنا استخدمنا بوابة مفتوحة المصدر اسمها Kong. الإعدادات تبعتها بتكون بملف YAML بسيط وواضح. شوفوا هالمثال اللي بوصف كيف عرفنا خدمة المستخدمين خلف البوابة:
مثال إعدادات باستخدام Kong
هذا ملف `kong.yml` بسيط جداً لتعريف خدمة وتوجيه الطلبات إليها مع تفعيل المصادقة:
_format_version: "3.0"
# 1. تعريف الخدمة الداخلية
# هنا نخبر البوابة عن وجود خدمة اسمها user-service
# وعنوانها الداخلي الذي لا يمكن الوصول إليه من الخارج
services:
- name: user-service
url: http://10.0.1.25:8080 # IP داخلي للخدمة
# 2. تعريف المسار العام (Route)
# هنا نربط مسار عام (public path) بالخدمة الداخلية
routes:
- name: users-route
service: user-service
paths:
- /users # أي طلب يجي على /users يتم توجيهه لـ user-service
# 3. تفعيل الإضافات (Plugins)
# هنا السحر الحقيقي! نطبق إضافة المصادقة على المسار
plugins:
- name: jwt
config:
claims_to_verify:
- exp
شرح الكود ببساطة:
يا بوابة Kong، اسمعي منيح: في عندي خدمة اسمها `user-service` وعنوانها الداخلي `http://10.0.1.25:8080`. أي طلب بستقبلِه على المسار العام `/users`، أول اشي تأكدي إنه معاه توكن JWT صالح ومش منتهي الصلاحية (عن طريق `claims_to_verify: [exp]`). إذا كل شي تمام، ابعتي الطلب لهداك العنوان الداخلي. غير هيك، ارفضي الطلب.
بهذا الملف البسيط، أمّنا خدمة كاملة وعزلناها عن العالم الخارجي في دقائق.
نصائح من خبرة أبو عمر
بعد رحلتنا هاي، جمعتلكم كم نصيحة من القلب:
- ابدأ بسيطًا، ولكن فكّر بالمستقبل: إذا عندك خدمتين أو ثلاث، يمكن ما تحتاج بوابة API معقدة من أول يوم. لكن وأنت بتصمم نظامك، خلي فكرة وجودها بالمستقبل في بالك. لا تربط خدماتك ببعضها بشكل مباشر.
- اختر بوابتك بحكمة: في حلول مفتوحة المصدر قوية زي (Kong, Tyk, KrakenD)، وفي حلول سحابية مُدارة زي (AWS API Gateway, Azure API Management). الحلول السحابية أسهل للبدء لكن ممكن “تحبسك” مع مزود الخدمة. الحلول المفتوحة المصدر بتعطيك حرية أكبر لكن بدها شوية شغل صيانة.
- لا تجعل البوابة “عنق الزجاجة” (Bottleneck): البوابة صارت أهم قطعة في نظامك. لو وقعت، كل النظام بوقع. لازم تتأكد إنها قابلة للتوسع (scalable) ومتاحة دائمًا (highly available).
- البوابة ليست حلاً سحرياً لكل شيء: هي بتنظم المرور والأمان على الأطراف، لكنها ما بتصلح الكود السيء داخل خدماتك. جودة الكود الداخلي بتضل مسؤوليتك.
الخلاصة: من الفوضى إلى النظام 🚀
التحول من الخدمات المصغرة الفوضوية إلى بنية تحتية مُنظمة باستخدام بوابة الـ API كان واحد من أفضل القرارات التقنية اللي أخذناها. وفر علينا ساعات لا تحصى من تصحيح الأخطاء، وحمى نظامنا من ثغرات أمنية كانت ممكن تكون كارثية، وخلى حياة فريق المطورين (خصوصاً الواجهات الأمامية) أسهل بكثير.
إذا كنت بتعاني من نفس الفوضى اللي كنا فيها، أو بتفكر تبدأ رحلتك مع الخدمات المصغرة، نصيحتي لك: لا تستهين بقوة بوابة الـ API. هي مش مجرد أداة، هي العقل المدبر والمنظم اللي بيحول مجموعة خدمات متناثرة إلى نظام متكامل، قوي، وآمن.
لا تخاف من تعقيد الخدمات المصغرة، بس اعرف كيف تروّضها. بوابة الـ API هي عصاتك السحرية. والله ولي التوفيق.