نصيحة: استخدم URL-based للواجهات العامة، واحتفظ بتوثيق واضح لسياسة الترحيل (deprecation period، رسائل تحذير في الردود).
8 — الأمان (Security)
TLS (HTTPS) إلزامي لكل الطلبات.
مصادقة (Authentication): API Keys, Bearer JWT, OAuth2 (authorization code / client credentials).
تفويض (Authorization): تحقق من الصلاحيات (RBAC / ACL / scopes).
احمِ رؤوس حساسة، لا تعرض الحقول السرية في الردود.
التجديد الآمن للتوكنات (refresh tokens) وتدوير المفاتيح (key rotation).
حماية ضد CSRF للبراوزر، وإعداد CORS محدود المنشأ (Origin).
تشفير البيانات الحساسة عند الراحة (at rest) والنقل.
تدقيق وlog للأحداث الأمنية مع التنبيه (alerts).
مثال رأس مصادقة:
Request Header Authorization: Bearer <token>
9 — معايير إضافية مهمة (لم تُذكر بالوعي في الصورة)
الاستجابة بالأخطاء الموحدة (Consistent Error Format):
مثال JSON ثابت:
{ "error": { "code": "invalid_input", "message": "Email is required", "details": { "field": "email" }, "documentation_url": "https://api.example.com/docs/errors#invalid_input" } }
حالات HTTP مناسبة:
200 OK، 201 Created، 204 No Content، 400 Bad Request، 401 Unauthorized، 403 Forbidden، 404 Not Found، 409 Conflict، 429 Too Many Requests، 500 Internal Server Error.
Caching: دعم ETag, If-None-Match, Cache-Control لزيادة الأداء.
مراقبة وقياس (Observability): Metrics, Tracing, Logs, Error rates, SLOs.
توثيق واضح: استخدم OpenAPI/Swagger، مثال طلب/استجابة، نماذج، أكواد خطأ.
اختبارات عقود (Contract Tests): حماية التوافق بين الخدمة والعميل.
حجم الصفحة الافتراضي والحد الأقصى: فرض حدود limit كمحافظة على الأداء.
Content Negotiation: دعم Accept و Content-Type بوضوح إن لزم (JSON، XML).
سياسة إزالة القدامى (Deprecation): رؤوس أو رسائل تُبلغ العملاء قبل إيقاف endpoint.
أمثلة عملية سريعة (curl)
طلب صفحة منتجات مع فلتر وفرز:
curl "https://api.example.com/products?filter[category]=books&min_price=5&sort=-created_at&limit=20" \ -H "Authorization: Bearer <token>"
إنشاء مورد مع Idempotency Key:
curl -X POST "https://api.example.com/payments" \ -H "Authorization: Bearer <token>" \ -H "Idempotency-Key: order-12345" \ -H "Content-Type: application/json" \ -d '{"amount":100, "currency":"USD"}'
خلاصة سريعة ونصيحة عملية
ابدأ بمواصفات واضحة (OpenAPI)، سمِّ endpoints بعناية، طبّق idempotency حيث يلزم، وفرّ Pagination مناسبًا، وثّق طرق الفرز والتصفية، ضبط Rate Limiting، وفكّر جيدًا في استراتيجية Versioning، ولا تغفل عن الأمان والـ observability.
هذه الممارسات تجعل API قابلًا للتوسّع، سهل الاستخدام للمطوّرين، وأكثر أمانًا واستقرارًا للإنتاج.
8 — الأمان (Security)
TLS (HTTPS) إلزامي لكل الطلبات.
مصادقة (Authentication): API Keys, Bearer JWT, OAuth2 (authorization code / client credentials).
تفويض (Authorization): تحقق من الصلاحيات (RBAC / ACL / scopes).
احمِ رؤوس حساسة، لا تعرض الحقول السرية في الردود.
التجديد الآمن للتوكنات (refresh tokens) وتدوير المفاتيح (key rotation).
حماية ضد CSRF للبراوزر، وإعداد CORS محدود المنشأ (Origin).
تشفير البيانات الحساسة عند الراحة (at rest) والنقل.
تدقيق وlog للأحداث الأمنية مع التنبيه (alerts).
مثال رأس مصادقة:
Request Header Authorization: Bearer <token>
9 — معايير إضافية مهمة (لم تُذكر بالوعي في الصورة)
الاستجابة بالأخطاء الموحدة (Consistent Error Format):
مثال JSON ثابت:
{ "error": { "code": "invalid_input", "message": "Email is required", "details": { "field": "email" }, "documentation_url": "https://api.example.com/docs/errors#invalid_input" } }
حالات HTTP مناسبة:
200 OK، 201 Created، 204 No Content، 400 Bad Request، 401 Unauthorized، 403 Forbidden، 404 Not Found، 409 Conflict، 429 Too Many Requests، 500 Internal Server Error.
Caching: دعم ETag, If-None-Match, Cache-Control لزيادة الأداء.
مراقبة وقياس (Observability): Metrics, Tracing, Logs, Error rates, SLOs.
توثيق واضح: استخدم OpenAPI/Swagger، مثال طلب/استجابة، نماذج، أكواد خطأ.
اختبارات عقود (Contract Tests): حماية التوافق بين الخدمة والعميل.
حجم الصفحة الافتراضي والحد الأقصى: فرض حدود limit كمحافظة على الأداء.
Content Negotiation: دعم Accept و Content-Type بوضوح إن لزم (JSON، XML).
سياسة إزالة القدامى (Deprecation): رؤوس أو رسائل تُبلغ العملاء قبل إيقاف endpoint.
أمثلة عملية سريعة (curl)
طلب صفحة منتجات مع فلتر وفرز:
curl "https://api.example.com/products?filter[category]=books&min_price=5&sort=-created_at&limit=20" \ -H "Authorization: Bearer <token>"
إنشاء مورد مع Idempotency Key:
curl -X POST "https://api.example.com/payments" \ -H "Authorization: Bearer <token>" \ -H "Idempotency-Key: order-12345" \ -H "Content-Type: application/json" \ -d '{"amount":100, "currency":"USD"}'
خلاصة سريعة ونصيحة عملية
ابدأ بمواصفات واضحة (OpenAPI)، سمِّ endpoints بعناية، طبّق idempotency حيث يلزم، وفرّ Pagination مناسبًا، وثّق طرق الفرز والتصفية، ضبط Rate Limiting، وفكّر جيدًا في استراتيجية Versioning، ولا تغفل عن الأمان والـ observability.
هذه الممارسات تجعل API قابلًا للتوسّع، سهل الاستخدام للمطوّرين، وأكثر أمانًا واستقرارًا للإنتاج.
❤1
أولاً: JWT (JSON Web Token)
JWT هو معيار مفتوح لنقل المعلومات بين طرفين (Client ↔ Server) بشكل آمن نسبيًا.
الـ JWT يتكون من ثلاثة أجزاء:
Header: يحدد نوع التوكن وطريقة التشفير (مثل HS256).
Payload: يحتوي البيانات (Claims) مثل: userId, email, exp.
Signature: توقيع للتحقق أن التوكن لم يتم التلاعب به.
كيف يشتغل؟
المستخدم يسجل دخول بإسم المستخدم وكلمة المرور.
السيرفر يتأكد من صحة البيانات ويولد JWT موقّع.
التوكن يُرسل للعميل ويُخزن عادة في LocalStorage أو Cookies.
عند كل طلب جديد، العميل يرسل JWT في الـ Authorization Header.
السيرفر يتحقق من التوقيع ويقرر قبول أو رفض الطلب.
ميزة JWT: إنه "stateless" يعني السيرفر ما يحتاج يخزن جلسة لكل مستخدم.
مثال واقعي:
في تطبيقات مثل Netflix أو Spotify، بعد ما تسجل دخول، التوكن يحملك معك في كل طلب (تشغيل فيلم/أغنية).
ثانياً: PASETO (Platform-Agnostic Security Tokens)
PASETO هو بديل حديث لـ JWT، صمم لحل مشاكله. فكرته الأساسية: فرض استخدام خوارزميات آمنة بشكل افتراضي.
مكوناته الرئيسية:
Version (V1 أو V2).
Purpose (Public أو Local).
Payload (مشفر أو نص عادي).
أنواع PASETO:
Public PASETO: موقع (Signed) بمفتاح خاص/عام → يضمن سلامة البيانات لكن ليس سريتها.
Local PASETO: مشفر (Encrypted) بمفتاح سري → يضمن سرية البيانات.
كيف يشتغل؟
المستخدم يرسل بياناته.
السيرفر يولد PASETO بالتشفير المناسب.
العميل يرسل التوكن عند الطلبات.
السيرفر يفتح التوكن ويتحقق منه باستخدام المفتاح الصحيح.
ميزة PASETO: ما يسمح باستخدام خوارزميات ضعيفة مثل HS256، بل يفرض خوارزميات حديثة (ChaCha20-Poly1305, Ed25519).
مثال واقعي:
في تطبيقات البنوك أو أنظمة الدفع مثل PayPal أو Stripe، حيث أمان البيانات أهم من كل شيء، PASETO يوفر تشفير افتراضي أقوى.
الميزات والعيوب
ميزات JWT:
سهل الاستخدام ومدعوم في كل اللغات والأطر (Node.js, ASP.NET, Django...).
مناسب للتطبيقات الكبيرة (API, Microservices).
واسع الانتشار وموثق بشكل ضخم.
عيوب JWT:
يسمح باستخدام خوارزميات غير آمنة (مثل none, HS256 إذا أسيء استخدامها).
لا يشفر البيانات، فقط يوقعها → أي شخص معه التوكن يقدر يقرأ الـ Payload.
إذا تسرب التوكن، ما تقدر تبطله إلا بتغيير الـ secret أو عمل Blacklist.
ميزات PASETO:
أمان أفضل بخيارات افتراضية قوية (secure by default).
يدعم التوقيع والتشفير معًا (Integrity + Confidentiality).
يقلل من الأخطاء الأمنية الناتجة عن سوء اختيار الخوارزميات.
عيوب PASETO:
جديد نسبيًا → أقل انتشارًا وأدواته أقل من JWT.
بعض المكتبات والأنظمة لا تدعمه بشكل مباشر.
التعلم عليه أصعب شوية للمطورين الجدد.
تشبيه واقعي مبسط
JWT زي مفتاح إلكتروني لباب الفندق: يفتح لك الباب لكن أي شخص يشوف المفتاح يعرف رقم غرفتك وتاريخ صلاحيتك.
PASETO زي مفتاح مشفر: حتى لو أحد سرقه، ما يعرف التفاصيل لأنه التوكن نفسه مشفر ومبني بخوارزميات أقوى.
JWT هو معيار مفتوح لنقل المعلومات بين طرفين (Client ↔ Server) بشكل آمن نسبيًا.
الـ JWT يتكون من ثلاثة أجزاء:
Header: يحدد نوع التوكن وطريقة التشفير (مثل HS256).
Payload: يحتوي البيانات (Claims) مثل: userId, email, exp.
Signature: توقيع للتحقق أن التوكن لم يتم التلاعب به.
كيف يشتغل؟
المستخدم يسجل دخول بإسم المستخدم وكلمة المرور.
السيرفر يتأكد من صحة البيانات ويولد JWT موقّع.
التوكن يُرسل للعميل ويُخزن عادة في LocalStorage أو Cookies.
عند كل طلب جديد، العميل يرسل JWT في الـ Authorization Header.
السيرفر يتحقق من التوقيع ويقرر قبول أو رفض الطلب.
ميزة JWT: إنه "stateless" يعني السيرفر ما يحتاج يخزن جلسة لكل مستخدم.
مثال واقعي:
في تطبيقات مثل Netflix أو Spotify، بعد ما تسجل دخول، التوكن يحملك معك في كل طلب (تشغيل فيلم/أغنية).
ثانياً: PASETO (Platform-Agnostic Security Tokens)
PASETO هو بديل حديث لـ JWT، صمم لحل مشاكله. فكرته الأساسية: فرض استخدام خوارزميات آمنة بشكل افتراضي.
مكوناته الرئيسية:
Version (V1 أو V2).
Purpose (Public أو Local).
Payload (مشفر أو نص عادي).
أنواع PASETO:
Public PASETO: موقع (Signed) بمفتاح خاص/عام → يضمن سلامة البيانات لكن ليس سريتها.
Local PASETO: مشفر (Encrypted) بمفتاح سري → يضمن سرية البيانات.
كيف يشتغل؟
المستخدم يرسل بياناته.
السيرفر يولد PASETO بالتشفير المناسب.
العميل يرسل التوكن عند الطلبات.
السيرفر يفتح التوكن ويتحقق منه باستخدام المفتاح الصحيح.
ميزة PASETO: ما يسمح باستخدام خوارزميات ضعيفة مثل HS256، بل يفرض خوارزميات حديثة (ChaCha20-Poly1305, Ed25519).
مثال واقعي:
في تطبيقات البنوك أو أنظمة الدفع مثل PayPal أو Stripe، حيث أمان البيانات أهم من كل شيء، PASETO يوفر تشفير افتراضي أقوى.
الميزات والعيوب
ميزات JWT:
سهل الاستخدام ومدعوم في كل اللغات والأطر (Node.js, ASP.NET, Django...).
مناسب للتطبيقات الكبيرة (API, Microservices).
واسع الانتشار وموثق بشكل ضخم.
عيوب JWT:
يسمح باستخدام خوارزميات غير آمنة (مثل none, HS256 إذا أسيء استخدامها).
لا يشفر البيانات، فقط يوقعها → أي شخص معه التوكن يقدر يقرأ الـ Payload.
إذا تسرب التوكن، ما تقدر تبطله إلا بتغيير الـ secret أو عمل Blacklist.
ميزات PASETO:
أمان أفضل بخيارات افتراضية قوية (secure by default).
يدعم التوقيع والتشفير معًا (Integrity + Confidentiality).
يقلل من الأخطاء الأمنية الناتجة عن سوء اختيار الخوارزميات.
عيوب PASETO:
جديد نسبيًا → أقل انتشارًا وأدواته أقل من JWT.
بعض المكتبات والأنظمة لا تدعمه بشكل مباشر.
التعلم عليه أصعب شوية للمطورين الجدد.
تشبيه واقعي مبسط
JWT زي مفتاح إلكتروني لباب الفندق: يفتح لك الباب لكن أي شخص يشوف المفتاح يعرف رقم غرفتك وتاريخ صلاحيتك.
PASETO زي مفتاح مشفر: حتى لو أحد سرقه، ما يعرف التفاصيل لأنه التوكن نفسه مشفر ومبني بخوارزميات أقوى.
مشهد بروتوكولات الـAPI اليوم — شرح عملي ومفصّل
هناك ستة بروتوكولات/أنماط هي الأكثر حضورًا عند بناء تكاملات وخدمات حديثة: REST، Webhooks، GraphQL، SOAP، WebSocket، gRPC. تحتها تظهر تقنيات مكملة مثل SSE، MQTT، AMQP وأنماط معمارية مثل EDA، ومعايير تبادل أعمال قديمة مثل EDI. فيما يلي شرح مركز مع متى تستخدم كل خيار ولماذا.
1) REST
ما هو؟ أسلوب معماري فوق HTTP (GET/POST/PUT/DELETE…) للتعامل مع “موارد” لها عناوين URL وتمثيلات JSON.
يناسب عندما:
CRUD على بيانات واضحة الكيانات: Users, Orders, Invoices…
واجهات عامة/شركاء يسهل عليهم الاستهلاك.
الحاجة للتخزين المؤقت (caching) وسياسات HTTP القياسية.
المزايا: بسيط، واسع التبني، أدوات غنية (OpenAPI/Swagger)، يسهل نسخه عبر المتصفّح وPostman.
التحديات: تجميع بيانات متعددة في طلب واحد قد يتطلب عدة مكالمات؛ التحميل الزائد/الناقص (over/under-fetch).
ملاحظات تصميم مهمة: ترقيم الإصدارات، معرّفات ثابتة، Idempotency-Key للعمليات الحسّاسة (مثل الدفع)، واستخدام ETag وCache-Control.
2) Webhooks
ما هو؟ نداء عكسي ترسله خدمتُك إلى URL يملكه الطرف الآخر عند وقوع حدث (payment.succeeded مثلًا).
يناسب عندما:
إعلام الأنظمة الشريكة بالأحداث فورًا بدون polling.
تكاملات ماركت بليس/بوابات دفع/مستودعات.
المزايا: آني، يقلّل الاستعلامات المتكررة.
التحديات: الاعتمادية (إعادة المحاولة مع backoff)، الأمن (توقيع HMAC وسرّ مشترك)، ترتيب الرسائل.
أفضل الممارسات:
توقيع كل رسالة وإرفاق timestamp لمنع إعادة التشغيل.
Retry-After + DLQ عند الفشل.
صفحة لإدارة الاشتراكات وHealth checks.
3) GraphQL
ما هو؟ طبقة استعلام تتيح للعميل طلب “بالضبط” الحقول التي يريدها عبر مخطط (Schema) موحّد.
يناسب عندما:
واجهات غنية (ويب/موبايل) تحتاج جمع بيانات من خدمات متعددة بكفاءة.
تقليل عدد الطلبات وتكييف الاستجابة بحسب شاشة العميل.
المزايا: تحكم دقيق في البيانات، نوعية قوية (strongly-typed schema)، introspection، توحيد بوابة بيانات.
التحديات: الحماية من الاستعلامات المكلفة (كسارة/عمق/تعقيد)، التخزين المؤقت أصعب من REST، أدوات رصد خاصة.
ملاحظات: استخدم حدودًا (limits) وquery cost، وPersisted Queries، وDataLoader لتجميع الاستدعاءات.
4) SOAP
ما هو؟ بروتوكول XML صارم مع WSDL وعمليات محددة، شائع في الأنظمة المؤسسية القديمة والجهات الحكومية.
يناسب عندما:
التكامل مع أنظمة قديمة/جهات رسمية لا تدعم إلا SOAP.
احتياج لميزات معيارية مثل WS-Security وTransactions.
المزايا: مواصفات أمنية وتعاملات قوية تاريخيًا.
التحديات: ثقل XML، صعوبة على فرق حديثة، بطء التطوير مقارنةً بـ REST/JSON.
5) WebSocket
ما هو؟ قناة ثنائية الاتجاه طويلة العمر فوق TCP (تبدأ عبر Handshake HTTP)، مناسبة للتحديث الفوري.
يناسب عندما:
محادثة فورية، لوحات حيّة، تعقّب مواقع، ألعاب.
الحاجة لبث من الخادم للعميل والعكس دون فتح طلبات متكررة.
المزايا: زمن كمون منخفض، ثنائية الاتجاه حقيقية.
التحديات: التوسّع والأمان (جلسات طويلة)، التوافق مع شبكات/Proxies، السقوط والعودة (reconnect) مع استئناف الحالة.
بدائل أخف: SSE عندما تحتاج بثًا من الخادم للعميل فقط.
6) gRPC
ما هو؟ إطار RPC عالي الأداء يعتمد HTTP/2 وProtocol Buffers للتسلسل (binary).
يناسب عندما:
اتصالات خدمة-إلى-خدمة (microservices) داخل الشبكة.
حاجات أداء عالية وبث ثنائي الاتجاه، وتعريف واجهات بنوعية صارمة.
المزايا: سريع جدًا، مخططات مُولِّدة للشيفرة، Streams، ضغط فعّال.
التحديات: أقل ملاءمة للمتصفح مباشرة (يُستخدم gRPC-Web)، أدوات تصحيح أقل بساطة من REST.
ملاحظات: أبقه داخليًا، وقدّم بوابة REST/GraphQL خارجية للاستهلاك العام.
تقنيات مُكمِّلة مذكورة في الرسم
SSE (Server-Sent Events): بث أحادي الاتجاه من الخادم للمتصفح عبر HTTP عادي؛ ممتاز للتحديثات الحيّة البسيطة والتنبيهات ولوحات الرصد عندما لا تحتاج قنوات ثنائية الاتجاه كاملة مثل WebSocket.
MQTT: بروتوكول Pub/Sub خفيف للشبكات غير المستقرة وIoT.
AMQP (مثل RabbitMQ): معيار رسائل للمؤسسات (صفوف، تبادل، توجيه) لتكامل غير متزامن وإزالة الازدحام عن الـAPI.
EDA (Event-Driven Architecture): نمط معماري يبني النظام حول أحداث ونواقل رسائل؛ غالبًا يستخدم AMQP/Kafka وWebhooks.
EDI: معايير قديمة لتبادل مستندات الأعمال (فواتير، أوامر شراء) بين مؤسسات؛ ما يزال موجودًا في سلاسل الإمداد.
كيف تختار؟ (دليل قرار سريع)
CRUD قياسي وواجهة للعامة → REST.
تجميع بيانات من خدمات متعددة وتقليل عدد الطلبات لواجهات غنية → GraphQL.
تنبيه الأطراف الخارجية عند وقوع حدث → Webhooks (+ توقيع HMAC وإعادة المحاولة).
هناك ستة بروتوكولات/أنماط هي الأكثر حضورًا عند بناء تكاملات وخدمات حديثة: REST، Webhooks، GraphQL، SOAP، WebSocket، gRPC. تحتها تظهر تقنيات مكملة مثل SSE، MQTT، AMQP وأنماط معمارية مثل EDA، ومعايير تبادل أعمال قديمة مثل EDI. فيما يلي شرح مركز مع متى تستخدم كل خيار ولماذا.
1) REST
ما هو؟ أسلوب معماري فوق HTTP (GET/POST/PUT/DELETE…) للتعامل مع “موارد” لها عناوين URL وتمثيلات JSON.
يناسب عندما:
CRUD على بيانات واضحة الكيانات: Users, Orders, Invoices…
واجهات عامة/شركاء يسهل عليهم الاستهلاك.
الحاجة للتخزين المؤقت (caching) وسياسات HTTP القياسية.
المزايا: بسيط، واسع التبني، أدوات غنية (OpenAPI/Swagger)، يسهل نسخه عبر المتصفّح وPostman.
التحديات: تجميع بيانات متعددة في طلب واحد قد يتطلب عدة مكالمات؛ التحميل الزائد/الناقص (over/under-fetch).
ملاحظات تصميم مهمة: ترقيم الإصدارات، معرّفات ثابتة، Idempotency-Key للعمليات الحسّاسة (مثل الدفع)، واستخدام ETag وCache-Control.
2) Webhooks
ما هو؟ نداء عكسي ترسله خدمتُك إلى URL يملكه الطرف الآخر عند وقوع حدث (payment.succeeded مثلًا).
يناسب عندما:
إعلام الأنظمة الشريكة بالأحداث فورًا بدون polling.
تكاملات ماركت بليس/بوابات دفع/مستودعات.
المزايا: آني، يقلّل الاستعلامات المتكررة.
التحديات: الاعتمادية (إعادة المحاولة مع backoff)، الأمن (توقيع HMAC وسرّ مشترك)، ترتيب الرسائل.
أفضل الممارسات:
توقيع كل رسالة وإرفاق timestamp لمنع إعادة التشغيل.
Retry-After + DLQ عند الفشل.
صفحة لإدارة الاشتراكات وHealth checks.
3) GraphQL
ما هو؟ طبقة استعلام تتيح للعميل طلب “بالضبط” الحقول التي يريدها عبر مخطط (Schema) موحّد.
يناسب عندما:
واجهات غنية (ويب/موبايل) تحتاج جمع بيانات من خدمات متعددة بكفاءة.
تقليل عدد الطلبات وتكييف الاستجابة بحسب شاشة العميل.
المزايا: تحكم دقيق في البيانات، نوعية قوية (strongly-typed schema)، introspection، توحيد بوابة بيانات.
التحديات: الحماية من الاستعلامات المكلفة (كسارة/عمق/تعقيد)، التخزين المؤقت أصعب من REST، أدوات رصد خاصة.
ملاحظات: استخدم حدودًا (limits) وquery cost، وPersisted Queries، وDataLoader لتجميع الاستدعاءات.
4) SOAP
ما هو؟ بروتوكول XML صارم مع WSDL وعمليات محددة، شائع في الأنظمة المؤسسية القديمة والجهات الحكومية.
يناسب عندما:
التكامل مع أنظمة قديمة/جهات رسمية لا تدعم إلا SOAP.
احتياج لميزات معيارية مثل WS-Security وTransactions.
المزايا: مواصفات أمنية وتعاملات قوية تاريخيًا.
التحديات: ثقل XML، صعوبة على فرق حديثة، بطء التطوير مقارنةً بـ REST/JSON.
5) WebSocket
ما هو؟ قناة ثنائية الاتجاه طويلة العمر فوق TCP (تبدأ عبر Handshake HTTP)، مناسبة للتحديث الفوري.
يناسب عندما:
محادثة فورية، لوحات حيّة، تعقّب مواقع، ألعاب.
الحاجة لبث من الخادم للعميل والعكس دون فتح طلبات متكررة.
المزايا: زمن كمون منخفض، ثنائية الاتجاه حقيقية.
التحديات: التوسّع والأمان (جلسات طويلة)، التوافق مع شبكات/Proxies، السقوط والعودة (reconnect) مع استئناف الحالة.
بدائل أخف: SSE عندما تحتاج بثًا من الخادم للعميل فقط.
6) gRPC
ما هو؟ إطار RPC عالي الأداء يعتمد HTTP/2 وProtocol Buffers للتسلسل (binary).
يناسب عندما:
اتصالات خدمة-إلى-خدمة (microservices) داخل الشبكة.
حاجات أداء عالية وبث ثنائي الاتجاه، وتعريف واجهات بنوعية صارمة.
المزايا: سريع جدًا، مخططات مُولِّدة للشيفرة، Streams، ضغط فعّال.
التحديات: أقل ملاءمة للمتصفح مباشرة (يُستخدم gRPC-Web)، أدوات تصحيح أقل بساطة من REST.
ملاحظات: أبقه داخليًا، وقدّم بوابة REST/GraphQL خارجية للاستهلاك العام.
تقنيات مُكمِّلة مذكورة في الرسم
SSE (Server-Sent Events): بث أحادي الاتجاه من الخادم للمتصفح عبر HTTP عادي؛ ممتاز للتحديثات الحيّة البسيطة والتنبيهات ولوحات الرصد عندما لا تحتاج قنوات ثنائية الاتجاه كاملة مثل WebSocket.
MQTT: بروتوكول Pub/Sub خفيف للشبكات غير المستقرة وIoT.
AMQP (مثل RabbitMQ): معيار رسائل للمؤسسات (صفوف، تبادل، توجيه) لتكامل غير متزامن وإزالة الازدحام عن الـAPI.
EDA (Event-Driven Architecture): نمط معماري يبني النظام حول أحداث ونواقل رسائل؛ غالبًا يستخدم AMQP/Kafka وWebhooks.
EDI: معايير قديمة لتبادل مستندات الأعمال (فواتير، أوامر شراء) بين مؤسسات؛ ما يزال موجودًا في سلاسل الإمداد.
كيف تختار؟ (دليل قرار سريع)
CRUD قياسي وواجهة للعامة → REST.
تجميع بيانات من خدمات متعددة وتقليل عدد الطلبات لواجهات غنية → GraphQL.
تنبيه الأطراف الخارجية عند وقوع حدث → Webhooks (+ توقيع HMAC وإعادة المحاولة).
❤1
بث فوري أحادي الاتجاه للمتصفح (تنبيهات/لوحات) → SSE، وإن احتجت محادثة/تفاعل ثنائي الاتجاه → WebSocket.
تواصل داخلي عالي الأداء بين الميكروسيرفس → gRPC.
تكاملات حكومية/قديمة تُلزِم XML/WSDL → SOAP.
أنظمة IoT أو شبكات ضعيفة → MQTT.
مهام غير متزامنة مرتّبة وضمان التسليم → AMQP مع طوابير ورسائل معاد محاولة.
اعتبارات أمان وأداء مشتركة
المصادقة والتفويض: OAuth2/OIDC للواجهات العامة، مفاتيح خدمة + mTLS بين الخدمات، وتوقيع Webhooks.
الاعتمادية: Idempotency في العمليات الحساسة، سياسات Retry مع Backoff، ورسائل “مرة واحدة على الأكثر/الأقل”.
الرصد: تتبّع موزّع (Trace/Span IDs)، قياسات Latency/Throughput/Error Rate، وسجلات غنية.
التوافق والتخزين المؤقت: REST يستفيد من Cache طبقة HTTP؛ GraphQL يحتاج إستراتيجيات خاصة؛ gRPC يعتمد عادةً على Cache طبقة التطبيق.
الإصدارات: حافظ على توافق خلفي؛ استخدم Versioning للـREST وSemVer لملفات proto وGraphQL deprecations.
توصية تطبيقية لنظام مثل Genius Link (محاسبي متعدد المستأجرين)
واجهة عامة للمطورين والعملاء: REST موثّق بـ OpenAPI.
لوحات داخلية غنيّة/تجميع بيانات متعددة: GraphQL Gateway داخلي للواجهات.
تنبيهات فورية (سند قُبِض/فاتورة دفعت): Webhooks للشركاء + SSE/WebSocket لتطبيقات الويب.
تكاملات حكومية/بنكية قديمة: SOAP/EDI عند الاضطرار.
بين الخدمات (حسابات/مدفوعات/تحليلات): gRPC داخل الشبكة + AMQP لطوابير المهام.
موبايل وشبكات ضعيفة: فكّر في مزج REST مع تخزين محلي ومزامنة، وMQTT إذا ظهرت سيناريوهات اتصال متقطع.
تواصل داخلي عالي الأداء بين الميكروسيرفس → gRPC.
تكاملات حكومية/قديمة تُلزِم XML/WSDL → SOAP.
أنظمة IoT أو شبكات ضعيفة → MQTT.
مهام غير متزامنة مرتّبة وضمان التسليم → AMQP مع طوابير ورسائل معاد محاولة.
اعتبارات أمان وأداء مشتركة
المصادقة والتفويض: OAuth2/OIDC للواجهات العامة، مفاتيح خدمة + mTLS بين الخدمات، وتوقيع Webhooks.
الاعتمادية: Idempotency في العمليات الحساسة، سياسات Retry مع Backoff، ورسائل “مرة واحدة على الأكثر/الأقل”.
الرصد: تتبّع موزّع (Trace/Span IDs)، قياسات Latency/Throughput/Error Rate، وسجلات غنية.
التوافق والتخزين المؤقت: REST يستفيد من Cache طبقة HTTP؛ GraphQL يحتاج إستراتيجيات خاصة؛ gRPC يعتمد عادةً على Cache طبقة التطبيق.
الإصدارات: حافظ على توافق خلفي؛ استخدم Versioning للـREST وSemVer لملفات proto وGraphQL deprecations.
توصية تطبيقية لنظام مثل Genius Link (محاسبي متعدد المستأجرين)
واجهة عامة للمطورين والعملاء: REST موثّق بـ OpenAPI.
لوحات داخلية غنيّة/تجميع بيانات متعددة: GraphQL Gateway داخلي للواجهات.
تنبيهات فورية (سند قُبِض/فاتورة دفعت): Webhooks للشركاء + SSE/WebSocket لتطبيقات الويب.
تكاملات حكومية/بنكية قديمة: SOAP/EDI عند الاضطرار.
بين الخدمات (حسابات/مدفوعات/تحليلات): gRPC داخل الشبكة + AMQP لطوابير المهام.
موبايل وشبكات ضعيفة: فكّر في مزج REST مع تخزين محلي ومزامنة، وMQTT إذا ظهرت سيناريوهات اتصال متقطع.
❤1
التحكّم في الوصول يحدّد من يدخل ومن يُمنع — لكن القواعد تختلف:
التحكّم المستند للأدوار (RBAC): الوصول مبني على أدوار (مثل: Maintainer, Viewer). بسيط وقابل للتوسّع.
التحكّم المستند للسمات (ABAC): الوصول مبني على سمات/خصائص (مستخدم، مورد، بيئة). مرن جدًا، لكنه أعقد.
قوائم التحكم بالوصول (ACL): أذونات صريحة لكل مستخدم أو مجموعة. مباشر، لكن يصعب إدارته على نطاق واسع.
RBAC = أدوار.
ABAC = سمات.
ACL = أذونات صريحة.
سؤال للتفكير: هل اضطررت يومًا للانتقال من نموذج لآخر؟ ما الذي دفعك للتغيير؟
التحكّم المستند للأدوار (RBAC): الوصول مبني على أدوار (مثل: Maintainer, Viewer). بسيط وقابل للتوسّع.
التحكّم المستند للسمات (ABAC): الوصول مبني على سمات/خصائص (مستخدم، مورد، بيئة). مرن جدًا، لكنه أعقد.
قوائم التحكم بالوصول (ACL): أذونات صريحة لكل مستخدم أو مجموعة. مباشر، لكن يصعب إدارته على نطاق واسع.
RBAC = أدوار.
ABAC = سمات.
ACL = أذونات صريحة.
سؤال للتفكير: هل اضطررت يومًا للانتقال من نموذج لآخر؟ ما الذي دفعك للتغيير؟
❤2
Forwarded from DataBase قواعد بيانات (Pro. Anwar Al-saiary)
الدكتور أحمد بالخير... المدير العام و القائد العزيز لشركتنا 🤍
https://youtu.be/ioJQ1qp3Bmk?si=3PbwcwXvTEc0k6cH
https://youtu.be/ioJQ1qp3Bmk?si=3PbwcwXvTEc0k6cH
YouTube
ثورة الإدارة الصحية: كيف تُعيد أنظمة (HMS) تشكيل مستقبل الرعاية؟
يسعدنا في هذه الحلقة أن نستضيف أحد أبرز القيادات الوطنية في مجال التحول الرقمي الصحي،
الدكتور أحمد بن محمد بلخير، هو طبيب اطفال ومتخصص في المعلوماتية الصحية، متميز في الإبداع والابتكار التقني،
رائد في بناء وتطوير منظومة الصحة الرقمية في المملكة العربية السعودية،…
الدكتور أحمد بن محمد بلخير، هو طبيب اطفال ومتخصص في المعلوماتية الصحية، متميز في الإبداع والابتكار التقني،
رائد في بناء وتطوير منظومة الصحة الرقمية في المملكة العربية السعودية،…
هل صادفت شاشة منتجات “تفلاش” بيانات ناقصة… ثم تبدأ الطلبات تتكرر على الـ API بدون سبب؟
في MyApp واجهنا سيناريو شائع في Local-First داخل الـ SDK:
عند عرض Product List، كل منتج يحتاج Reference Data: Section / Unit / Manufacturer.
لكن عند انتهاء TTL تصبح البيانات Stale.
⚠️ المشكلة (The Blind Spot)
بدون سياق مزامنة مثل since أو lastSentAt، الـ SDK لا يعرف ما تغيّر فعلاً → يلجأ إلى Blind Full Fetch (Get All).
🔥 النتيجة
Redundant API Calls + High Server Load + Poor UX + نفس الداتا تُرسل مراراً.
✅ الحل
Delta/Incremental Sync + إرسال since = lastSentAt عند إعادة الطلب،
مع نافذة منع تكرار (10 دقائق) + (اختياري) Stale-While-Revalidate،
ومع ضغط UI العالي: Single-Flight / In-Flight Deduplication.
هل تستخدمون updatedSince / ETag / lastSyncAt في مشاريعكم؟
شرح الحل في المنشورات القادمة
#API #MobileArchitecture #DistributedSystems
في MyApp واجهنا سيناريو شائع في Local-First داخل الـ SDK:
عند عرض Product List، كل منتج يحتاج Reference Data: Section / Unit / Manufacturer.
لكن عند انتهاء TTL تصبح البيانات Stale.
⚠️ المشكلة (The Blind Spot)
بدون سياق مزامنة مثل since أو lastSentAt، الـ SDK لا يعرف ما تغيّر فعلاً → يلجأ إلى Blind Full Fetch (Get All).
🔥 النتيجة
Redundant API Calls + High Server Load + Poor UX + نفس الداتا تُرسل مراراً.
✅ الحل
Delta/Incremental Sync + إرسال since = lastSentAt عند إعادة الطلب،
مع نافذة منع تكرار (10 دقائق) + (اختياري) Stale-While-Revalidate،
ومع ضغط UI العالي: Single-Flight / In-Flight Deduplication.
هل تستخدمون updatedSince / ETag / lastSyncAt في مشاريعكم؟
شرح الحل في المنشورات القادمة
#API #MobileArchitecture #DistributedSystems
حل مشكلة “الطلبات المكررة” في Reference Data بطريقة أبسط وأذكى داخل MyApp ✅
بدل ما الـ SDK يعيد جلب كل شيء عند انتهاء TTL أو عند تكرار فتح الشاشة، طبقنا 3 أفكار مع بعض:
1) Delta Sync (Incremental Updates)
كل مرة نطلب فقط التغييرات عبر:
?since=lastSentAt
يعني: “أعطني ما تغيّر منذ آخر مزامنة ناجحة” بدل Full Fetch.
2) Throttle Window (مثلاً 10 دقائق)
لو المستخدم أعاد فتح الشاشة أو كرر نفس الطلب خلال 10 دقائق:
لا نرسل API Call جديد → نكتفي بالمحلي.
وبعد انتهاء النافذة نسمح بطلب Delta جديد.
3) Stale-While-Revalidate (SWR)
نعرض البيانات المحلية فوراً (حتى لو قديمة قليلاً) ونحدّث بصمت في الخلفية.
النتيجة: تجربة أسرع بدون “فلاش” بيانات ناقصة.
📌 النتيجة النهائية:
Optimized Network ✅
Low Server Load ✅
Fast & Fluid UX ✅
Tiny Delta Payload بدل Massive Payload ✅
هل تستخدمون lastSyncAt / lastSentAt أو Delta Sync في مشاريعكم؟
#API #MobileArchitecture #DistributedSystems
بدل ما الـ SDK يعيد جلب كل شيء عند انتهاء TTL أو عند تكرار فتح الشاشة، طبقنا 3 أفكار مع بعض:
1) Delta Sync (Incremental Updates)
كل مرة نطلب فقط التغييرات عبر:
?since=lastSentAt
يعني: “أعطني ما تغيّر منذ آخر مزامنة ناجحة” بدل Full Fetch.
2) Throttle Window (مثلاً 10 دقائق)
لو المستخدم أعاد فتح الشاشة أو كرر نفس الطلب خلال 10 دقائق:
لا نرسل API Call جديد → نكتفي بالمحلي.
وبعد انتهاء النافذة نسمح بطلب Delta جديد.
3) Stale-While-Revalidate (SWR)
نعرض البيانات المحلية فوراً (حتى لو قديمة قليلاً) ونحدّث بصمت في الخلفية.
النتيجة: تجربة أسرع بدون “فلاش” بيانات ناقصة.
📌 النتيجة النهائية:
Optimized Network ✅
Low Server Load ✅
Fast & Fluid UX ✅
Tiny Delta Payload بدل Massive Payload ✅
هل تستخدمون lastSyncAt / lastSentAt أو Delta Sync في مشاريعكم؟
#API #MobileArchitecture #DistributedSystems
مشكلة شائعة في Local-First: “Race Condition” تسبّب رحلات API مكررة 🚨
تخيّل شاشة Product List تُرندر عدة عناصر في نفس اللحظة (Product A / B / C…).
كل منتج يحتاج نفس الـ Reference Data مثل: Section #4.
الـ SDK يعمل Local-First → يفحص Local DB (Cache) أولاً.
⚠️ أين المشكلة؟
لأن الطلبات متزامنة، الجميع يصلون للكاش قبل أن يكتب أول طلب النتيجة:
Local DB = MISS (Not Found Yet)
فيقوم كل منتج بإطلاق طلب شبكة مستقل لنفس البيانات…
فتتحول العملية إلى 20+ طلب متطابق قبل أن يكتمل الأول.
🔥 الأثر على الخلفية (Backend)
- High Concurrency Load
- Wasted Bandwidth
- Risk of Rate Limiting
- UX أبطأ بسبب ازدحام الشبكة
🧠 المصطلحات الشائعة
- Cache Stampede / Thundering Herd
- Race Condition (In Local-First Cache)
- Redundant API Calls (وأحياناً تُرى كـ N+1 / Over-fetching حسب السياق)
✅ كيف نعالجها عادة؟
- Single-Flight / In-Flight Deduplication: “طلب واحد لكل مفتاح” والبقية تنتظر نفس الـ Future/Promise
- Request Coalescing: تجميع الطلبات المتطابقة
- (اختياري) Prefetch/Batch للـ Reference Data عند تحميل المنتجات
هل واجهت هذا السيناريو في تطبيقك؟ وكيف تعاملت معه؟
الحل في المنشورات القادمة
#API #MobileArchitecture #DistributedSystems
تخيّل شاشة Product List تُرندر عدة عناصر في نفس اللحظة (Product A / B / C…).
كل منتج يحتاج نفس الـ Reference Data مثل: Section #4.
الـ SDK يعمل Local-First → يفحص Local DB (Cache) أولاً.
⚠️ أين المشكلة؟
لأن الطلبات متزامنة، الجميع يصلون للكاش قبل أن يكتب أول طلب النتيجة:
Local DB = MISS (Not Found Yet)
فيقوم كل منتج بإطلاق طلب شبكة مستقل لنفس البيانات…
فتتحول العملية إلى 20+ طلب متطابق قبل أن يكتمل الأول.
🔥 الأثر على الخلفية (Backend)
- High Concurrency Load
- Wasted Bandwidth
- Risk of Rate Limiting
- UX أبطأ بسبب ازدحام الشبكة
🧠 المصطلحات الشائعة
- Cache Stampede / Thundering Herd
- Race Condition (In Local-First Cache)
- Redundant API Calls (وأحياناً تُرى كـ N+1 / Over-fetching حسب السياق)
✅ كيف نعالجها عادة؟
- Single-Flight / In-Flight Deduplication: “طلب واحد لكل مفتاح” والبقية تنتظر نفس الـ Future/Promise
- Request Coalescing: تجميع الطلبات المتطابقة
- (اختياري) Prefetch/Batch للـ Reference Data عند تحميل المنتجات
هل واجهت هذا السيناريو في تطبيقك؟ وكيف تعاملت معه؟
الحل في المنشورات القادمة
#API #MobileArchitecture #DistributedSystems
حل “الطلبات المتزامنة المكررة” في Local-First: Request Coalescing (Single-flight) ✅
المشهد معروف:
شاشة Product List تُرندر عدة منتجات في نفس اللحظة (Product A / B / C…)
وكلهم يحتاجون نفس الـ Reference Data مثل: Get Section #4.
بدون حل، كلهم يطلقون API Calls متطابقة قبل ما يكتمل أول طلب ويكتب للكاش.
🧠 الحل: SDK Request Coordinator (In-flight Map)
نضيف طبقة داخل الـ SDK تعمل كـ “مُنسّق طلبات”:
- تحتفظ بخريطة: Map<Key, Future>
- المفتاح = (Section#4)
- القيمة = Shared Future (طلب جاري)
كيف يعمل؟
1) أول طلب (Product A):
- لا يجد المفتاح في الـ In-flight Map
- ينشئ Shared Future
- ويرسل 1x API Request فقط
2) الطلبات التالية (Product B / C…):
- تجد Shared Future موجودة
- لا تُنشئ طلبات جديدة
- فقط “تنتظر” نفس الطلب الجاري (Await existing in-flight request)
📦 عند وصول النتيجة
- يتم كتابة البيانات إلى Local DB (Cache) ✔️
- يتم توزيع نفس النتيجة فوراً لكل عناصر UI المنتظرة (Fan-out) ✔️
📌 النتيجة
- 1x Optimized API Request بدل 20x Duplicate Requests
- Minimal Backend Load
- Fast & Consistent UX
- Cache يُملأ مرة واحدة ويُستخدم للجميع
🔎 مصطلحات مرتبطة
- Request Coalescing
- Single-flight Mechanism
- In-flight Deduplication
- Shared Future / Promise
- (وأحياناً يُستخدم كـ Lock per Key)
هل تطبّقون Single-flight في الـ SDK أو على مستوى Repository Layer؟
#API #MobileArchitecture #DistributedSystems
المشهد معروف:
شاشة Product List تُرندر عدة منتجات في نفس اللحظة (Product A / B / C…)
وكلهم يحتاجون نفس الـ Reference Data مثل: Get Section #4.
بدون حل، كلهم يطلقون API Calls متطابقة قبل ما يكتمل أول طلب ويكتب للكاش.
🧠 الحل: SDK Request Coordinator (In-flight Map)
نضيف طبقة داخل الـ SDK تعمل كـ “مُنسّق طلبات”:
- تحتفظ بخريطة: Map<Key, Future>
- المفتاح = (Section#4)
- القيمة = Shared Future (طلب جاري)
كيف يعمل؟
1) أول طلب (Product A):
- لا يجد المفتاح في الـ In-flight Map
- ينشئ Shared Future
- ويرسل 1x API Request فقط
2) الطلبات التالية (Product B / C…):
- تجد Shared Future موجودة
- لا تُنشئ طلبات جديدة
- فقط “تنتظر” نفس الطلب الجاري (Await existing in-flight request)
📦 عند وصول النتيجة
- يتم كتابة البيانات إلى Local DB (Cache) ✔️
- يتم توزيع نفس النتيجة فوراً لكل عناصر UI المنتظرة (Fan-out) ✔️
📌 النتيجة
- 1x Optimized API Request بدل 20x Duplicate Requests
- Minimal Backend Load
- Fast & Consistent UX
- Cache يُملأ مرة واحدة ويُستخدم للجميع
🔎 مصطلحات مرتبطة
- Request Coalescing
- Single-flight Mechanism
- In-flight Deduplication
- Shared Future / Promise
- (وأحياناً يُستخدم كـ Lock per Key)
هل تطبّقون Single-flight في الـ SDK أو على مستوى Repository Layer؟
#API #MobileArchitecture #DistributedSystems