Files
Siro/docs/server_architecture_feedback.md
T

291 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# تقرير التدقيق وتصميم بنية سيرفرات منصة Siro (نسخة محدثة ونهائية)
بناءً على التوضيح الدقيق للهيكلية الفعلية المعتمدة للمنظومة، يهدف هذا التقرير إلى تقديم تفصيل كامل للمكونات، ورسم طوبولوجيا الشبكة المطابقة للواقع، وحل مشكلة اتصال وتزامن خوادم الـ WebSockets مع خوادم الباك إند والعملاء.
---
## أولاً: الهيكلية المعتمدة للنظام (Actual Architecture Topology)
تتكون المنظومة من المكونات الأساسية التالية وتوزيعها كالتالي:
1. **موزع الأحمال (Load Balancer):** يقع في المقدمة لتلقي طلبات الـ API (HTTP/HTTPS) فقط وتوزيعها على خادمين.
2. **خوادم الـ API (Web Server A & B):** خوادم Stateless تستقبل الطلبات وتقوم بالمعالجة وحفظ الملفات، وتتصل بكل من قاعدة البيانات وذاكرة Redis المؤقتة.
3. **قاعدة البيانات الرئيسية (MySQL Master):** تحتوي على البيانات الأساسية ولها خادمان تابعان:
* **نسخة مطابقة (Replica):** للمزامنة الحية وتخفيف ضغط القراءة.
* **نسخة نسخ احتياطي (Dump Server):** لأخذ النسخ الاحتياطية الدورية دون التأثير على الأداء.
4. **خوادم الـ Redis:** تعمل كطبقة كاش ذكية أولى/ثانية أمام قاعدة البيانات لحفظ الجلسات، التحقق، ومعدل الطلبات، ولها خادم احتياطي (Replica).
5. **خوادم الـ WebSockets المنفصلة:**
* **سيرفر الموقع الجغرافي (Location Server):** خادم مستقل يستقبل إحداثيات GPS حية من تطبيق السائق.
* **سيرفر الرحلات (Ride/Passenger Server):** خادم مستقل يدير قنوات الاتصال الحي بين الراكب والسائق أثناء الرحلة.
* **ملاحظة:** تطبيق الفلاتر (الراكب والسائق) يتصل **مباشرة** بهذين السيرفرين عبر بروتوكول WS/WSS.
---
## ثانياً: حل معضلة اتصال الـ WebSockets (The WebSocket Integration Solution)
> [!IMPORTANT]
> ### السؤال الأساسي: كيف تتواصل خوادم الباك إند (Web Server A & B) مع خوادم الـ Sockets المنفصلة وتزامن حالة الرحلة؟
> بما أن خوادم الباك إند معزولة خلف موزع الأحمال، وتطبيقات الموبايل متصلة مباشرة بخوادم الـ Sockets، فإن أفضل طريقة تشغيلية ومعمارية للربط هي استخدام **Redis Pub/Sub (نظام النشر والاشتراك)** كجسر تواصل سريع جداً (Event Bus):
```mermaid
sequenceDiagram
autonumber
actor Driver as تطبيق السائق
participant WebAPI as خادم الباك إند (A أو B)
participant Redis as Redis Pub/Sub
participant RideSocket as سيرفر الـ Sockets (Ride)
actor Rider as تطبيق الراكب
Driver->>WebAPI: 1. قبول الرحلة (طلب API)
WebAPI->>WebAPI: 2. معالجة الطلب وحفظ الحالة بقاعدة البيانات
WebAPI->>Redis: 3. نشر حدث (Publish) -> "قبول_رحلة" لقناة Redis
Note over Redis: الحدث يحتوي على معرف الرحلة والراكب
Redis-->>RideSocket: 4. استلام الحدث فوراً (Subscription)
RideSocket->>Rider: 5. دفع تنبيه حقيقي (WebSocket Push) -> "السائق قبل رحلتك"
```
### مزايا هذا الحل:
* **Stateless API:** تبقى خوادم الباك إند خفيفة ولا تحتاج لمعرفة من متصل بأي سيرفر سوكت.
* **تزامن فوري:** تتم عملية النشر والاستلام عبر الـ Redis في أجزاء من الميلي ثانية.
* **فصل كامل للمسؤولية:** خوادم السوكت تركز فقط على الحفاظ على الاتصالات المفتوحة وإرسال البيانات، بينما خوادم الباك إند تركز على منطق العمل وحساب الأسعار.
---
## ثالثاً: مخطط طوبولوجيا الشبكة المقترح (Network Topology Diagram)
يوضح المخطط التالي العلاقة التفاعلية ومسارات اتصال تطبيقات الموبايل بالمنظومة:
```mermaid
graph TD
%% Clients
Rider([تطبيق الراكب])
Driver([تطبيق السائق])
%% API Routing
Rider -.->|1. API Requests HTTPS| LB[Load Balancer]
Driver -.->|1. API Requests HTTPS| LB
LB --> WebA[Web Server A]
LB --> WebB[Web Server B]
%% Direct Web Sockets Connection
Rider ==>|2. WebSocket WSS| RideSocket[Ride/Passenger Server]
Driver ==>|2. Live Location WSS| LocationSocket[Location Server]
%% Shared Storage for Uploads
WebA -->|Uploads| SharedStorage[(Shared Storage / NFS)]
WebB -->|Uploads| SharedStorage
%% Caching & PubSub Bridge
WebA --> RedisMaster[Redis Master]
WebB --> RedisMaster
RideSocket --> RedisMaster
LocationSocket --> RedisMaster
RedisMaster -->|Replication| RedisReplica[Redis Replica]
%% Databases
WebA --> DBMaster[(MySQL Master DB)]
WebB --> DBMaster
LocationSocket -.->|Save Trackings| DBMaster
RideSocket -.->|Save Ride States| DBMaster
%% DB Backup & Replication
DBMaster -->|Streaming| DBReplica[(MySQL Replica DB)]
DBMaster -->|Dumps| DBBackup[(MySQL Dump Server)]
```
---
## رابعاً: معالجة البيانات والتخزين المؤقت (Redis Caching Strategy)
* **البيانات المخزنة في Redis:** الجلسات النشطة (Sessions)، التوكنات المؤقتة للتحقق (OTP & JWT)، معدل الطلبات (Rate Limiting)، والبيانات الجغرافية المؤقتة للسائقين القريبين.
* **البيانات في MySQL:** بيانات المستخدمين، تفاصيل الرحلات، الحسابات المالية، سجلات الحظر والوثائق.
* عند طلب بيانات معينة (مثل الملف الشخصي)، يفحص السيرفر الـ Redis أولاً؛ إن لم يجدها (Cache Miss) يقرأها من MySQL Master/Replica ويخزنها في Redis لمرة ثانية لتسريع الطلبات القادمة.
---
## خامساً: خطة الشراء واختيار السيرفرات (Hosting & Sizing Recommendations)
بناءً على عروض الاستضافة المتاحة من شركتي **Netcup** و **Contabo**، تم تصميم خطة الشراء التالية لتوفر أفضل أداء مقابل السعر مع تحقيق توازن كامل للمنظومة:
### ١. مبررات اختيار الشركات لكل خدمة:
* **سيرفرات قواعد البيانات والـ Sockets والـ Redis (اختيار Netcup):** قواعد البيانات والاتصالات الحية تحتاج إلى **استقرار كامل للـ CPU** ونوعية رام مدعومة بكشف الأخطاء وتصحيحها (**ECC DDR5 RAM**)، بالإضافة إلى سرعة قراءة وكتابة فائقة للأقراص (NVMe SSD)، وهو ما تتفوق فيه Netcup بشكل قطعي.
* **سيرفرات الـ API المستقلة وسيرفر الخرائط (اختيار Contabo):** خوادم الـ API هي Stateless وتتطلب سعة ذاكرة رام عالية وأنوية معالجة بتكلفة اقتصادية لتوزيع الأحمال. كما أن سيرفر الخرائط يحتاج لمساحة ديسك ضخمة ورام كبيرة جداً لتحميل ملفات الـ PBF والـ Tiles، وتوفر Contabo أحجام رام ضخمة بأسعار منافسة جداً.
---
### ٢. جدول توزيع المشتريات ومواصفات السيرفرات (١٢ سيرفر):
| # | السيرفر ووظيفته | المواصفات المطلوبة | الشركة والخطة المقترحة | التكلفة (€/شهر) | التكلفة ($/شهر) | نوع القرص والتخزين |
| :---: | :--- | :---: | :--- | :---: | :---: | :---: |
| 1 | **موزع الأحمال (Load Balancer)** | 2GB RAM / 2 Cores | **Netcup:** VPS nano G11s | €2.58 | $2.92 | 60 GB SSD |
| 2 | **خادم الـ API الأول (Web Server A)** | 8GB RAM / 4 Cores | **Contabo:** Cloud VPS 10 | €4.40 | $4.97 | 75 GB NVMe |
| 3 | **خادم الـ API الثاني (Web Server B)** | 8GB RAM / 4 Cores | **Contabo:** Cloud VPS 10 | €4.40 | $4.97 | 75 GB NVMe |
| 4 | **قاعدة البيانات الرئيسية (MySQL Master)** | 32GB RAM / 12 Cores | **Netcup:** VPS 4000 G12 | €27.00 | $30.51 | 1 TB NVMe |
| 5 | **قاعدة البيانات الاحتياطية (MySQL Replica)** | 16GB RAM / 8 Cores | **Netcup:** VPS 2000 G12 | €16.17 | $18.27 | 512 GB NVMe |
| 6 | **سيرفر النسخ الاحتياطي (Dump DB)** | 4GB RAM / 2 Cores | **Netcup:** VPS 500 G12 | €4.96 | $5.61 | 128 GB NVMe |
| 7 | **ذاكرة Redis الرئيسية (Redis Master)** | 2GB RAM / 2 Cores | **Netcup:** VPS nano G11s | €2.58 | $2.92 | 60 GB SSD |
| 8 | **ذاكرة Redis الاحتياطية (Redis Replica)** | 2GB RAM / 2 Cores | **Netcup:** VPS nano G11s | €2.58 | $2.92 | 60 GB SSD |
| 9 | **سيرفر تتبع المواقع الحية (Location Server)** | 4GB RAM / 2 Cores | **Netcup:** VPS 500 G12 | €4.96 | $5.61 | 128 GB NVMe |
| 10 | **سيرفر حالة الرحلات (Passenger Socket)** | 2GB RAM / 2 Cores | **Netcup:** VPS nano G11s | €2.58 | $2.92 | 60 GB SSD |
| 11 | **سيرفر المدفوعات المستقل (Payments)** | 2GB RAM / 2 Cores | **Netcup:** VPS nano G11s | €2.58 | $2.92 | 60 GB SSD |
| 12 | **سيرفر الخرائط المخصص (SiroMaps)** | 64GB RAM / 16 Cores | **Contabo:** Cloud VPS 50 | €29.60 | $33.45 | 300 GB NVMe |
---
### ٣. ملخص التكلفة الشهرية الإجمالية:
| البند | التكلفة باليورو (€) | التكلفة بالدولار ($) |
| :--- | :---: | :---: |
| **إجمالي سيرفرات Netcup (9 سيرفرات)** | €65.99 | $74.58 |
| **إجمالي سيرفرات Contabo (3 سيرفرات)** | €38.40 | $43.39 |
| **الإجمالي الكلي للمنظومة (12 سيرفر)** | **€104.39** | **$117.97** |
> [!NOTE]
> سعر الصرف المستخدم: 1 يورو = 1.13 دولار أمريكي (تقريبي). الأسعار المذكورة هي أسعار الاشتراك الشهري فقط ولا تشمل رسوم الإعداد (Setup Fee) إن وجدت.
---
## سادساً: تقييم الأداء — كم تستوعب هذه المنظومة؟ (Capacity Estimation)
> [!IMPORTANT]
> ### الجواب المختصر: هذه البنية كافية ومتينة جداً لمنصة نقل ركاب بحجم سوق سوريا ومصر في مراحل التشغيل والنمو الأولى والمتوسطة.
### تقدير السعة حسب كل مكوّن:
| المكوّن | السعة التقديرية القصوى | الشرح والمبرر |
| :--- | :---: | :--- |
| **خوادم الـ API (Web A + B)** | ~2,000 - 3,000 طلب HTTP متزامن | كل سيرفر PHP-FPM بـ 8GB يخدم حوالي 1,000-1,500 طلب متزامن. مع سيرفرين خلف اللود بلانسر، تتضاعف السعة. |
| **سيرفر الموقع الجغرافي (Location WebSocket)** | ~10,000 - 15,000 سائق متصل في نفس اللحظة | Workerman على 4GB DDR5 يدير اتصالات خفيفة جداً (إحداثيات GPS كل 3 ثوانٍ). القيد هنا هو عدد الـ File Descriptors وليس الرام. |
| **سيرفر الرحلات (Passenger Socket)** | ~5,000 - 8,000 راكب متصل في نفس اللحظة | خفيف جداً كونه relay. كل اتصال يستهلك ~50KB رام فقط. |
| **قاعدة البيانات الرئيسية (MySQL Master)** | ~5,000 - 8,000 استعلام في الثانية | 32GB مع `innodb_buffer_pool_size=22GB` يخدم ملايين الصفوف بسرعة فائقة. مع الـ Replica يتضاعف أداء القراءة. |
| **Redis Master** | ~100,000+ عملية في الثانية | Redis على 2GB يخدم مئات آلاف العمليات/ثانية. حجم البيانات المخزنة (جلسات + كاش + GEO) لن يتجاوز 500MB في الذروة. |
| **سيرفر الخرائط (SiroMaps)** | ~500 - 1,000 طلب توجيه/ثانية | OSRM على 64GB رام يحمّل خريطة سوريا ومصر بالكامل في الذاكرة لسرعة فائقة. |
### تقدير السعة الإجمالية للمنصة:
| المقياس | السعة التقديرية |
| :--- | :---: |
| **عدد المستخدمين المسجلين (ركاب + سائقين)** | حتى **500,000+** مستخدم مسجل |
| **عدد السائقين المتصلين في نفس اللحظة (أوقات الذروة)** | حتى **10,000 - 15,000** سائق |
| **عدد الركاب النشطين في نفس اللحظة** | حتى **5,000 - 8,000** راكب |
| **عدد الرحلات اليومية** | حتى **20,000 - 40,000** رحلة/يوم |
| **عدد الرحلات المتزامنة في نفس اللحظة** | حتى **1,500 - 3,000** رحلة نشطة |
> [!TIP]
> ### للمقارنة: تطبيقات نقل ركاب كبرى في المنطقة مثل "كريم" و"بولت" في مراحلها الأولى كانت تعمل بمنظومات أصغر من هذه. هذه البنية تكفي لتغطية سوريا ومصر بالكامل حتى الوصول لعشرات الآلاف من الرحلات اليومية.
### عوامل تحدد متى تحتاج للترقية:
| المؤشر | القيمة الحدّية التي توجب الترقية |
| :--- | :---: |
| استخدام CPU لخوادم الـ API يتجاوز | 75% بشكل مستمر لأكثر من ساعة |
| استخدام الرام لقاعدة البيانات يتجاوز | 85% من الـ Buffer Pool |
| عدد اتصالات السوكت يتجاوز | 80% من حد الـ File Descriptors |
| زمن استجابة الـ API يتجاوز | 500 ميلي ثانية كمتوسط |
| حجم قاعدة بيانات التتبع (Tracking) يتجاوز | 50GB بدون سياسة تنظيف (TTL) |
---
## سابعاً: الشبكة الداخلية (Private Network / VLAN) — هل هي ضرورية؟
> [!CAUTION]
> ### الجواب القاطع: نعم، الشبكة الداخلية (VLAN) **إلزامية وليست اختيارية** في هذا التصميم. بدونها أنت تعرّض قاعدة البيانات وخادم Redis للإنترنت العام مباشرة، وهذه كارثة أمنية.
### لماذا الشبكة الداخلية ضرورية؟
| السبب | التفصيل |
| :--- | :--- |
| **١. الأمان (Security)** | قاعدة البيانات MySQL وخادم Redis يجب أن يكونا **معزولين تماماً** عن الإنترنت العام. لا يجب أن يملك أي شخص خارج المنظومة القدرة على الوصول إليهما. الشبكة الداخلية تجعل هذين الخادمين مرئيين فقط لخوادم الـ API والسوكت. |
| **٢. الأداء (Performance)** | الاتصال عبر الشبكة الداخلية أسرع بكثير (latency أقل بـ 5-10 أضعاف) من الاتصال عبر الإنترنت العام. استعلامات قاعدة البيانات ستستجيب بـ 0.1ms بدلاً من 1-5ms. |
| **٣. التكلفة (Cost)** | الترافيك عبر الشبكة الداخلية **مجاني بالكامل** ولا يُحسب من حصة الباندويث. بينما الترافيك العام يُحسب ويُكلّف. |
| **٤. عزل الخدمات (Isolation)** | لو تم اختراق أحد خوادم الـ API (لا سمح الله)، لن يتمكن المهاجم من الوصول لقاعدة البيانات عبر الإنترنت العام لأنها ببساطة غير مرئية من الخارج. |
### كيف يتم التطبيق عملياً؟
```mermaid
graph TD
subgraph PublicZone["المنطقة العامة (Public Zone)"]
LB[Load Balancer]
LocationSocket[Location Server]
RideSocket[Ride Server]
end
subgraph PrivateVLAN["الشبكة الداخلية الخاصة (Private VLAN)"]
WebA[Web Server A]
WebB[Web Server B]
RedisMaster[Redis Master]
RedisReplica[Redis Replica]
DBMaster[(MySQL Master)]
DBReplica[(MySQL Replica)]
DBBackup[(Dump Server)]
Payments[Payments Server]
end
subgraph MapsZone["منطقة الخرائط (Maps Zone)"]
Maps[SiroMaps Server]
end
Internet([الإنترنت]) -->|HTTPS| LB
Internet -->|WSS| LocationSocket
Internet -->|WSS| RideSocket
LB -->|Private IP| WebA
LB -->|Private IP| WebB
WebA -->|Private IP| RedisMaster
WebA -->|Private IP| DBMaster
WebB -->|Private IP| RedisMaster
WebB -->|Private IP| DBMaster
LocationSocket -->|Private IP| RedisMaster
RideSocket -->|Private IP| RedisMaster
WebA -->|Private IP| Maps
```
### التطبيق العملي لكل شركة:
| الشركة | طريقة إنشاء الشبكة الداخلية | الملاحظة |
| :--- | :--- | :--- |
| **Netcup** | من لوحة التحكم SCP → "vLAN" → إنشاء شبكة افتراضية وربط السيرفرات بها | Netcup يوفر VLAN مجاني بين سيرفراتك في نفس مركز البيانات (Datacenter). اختر جميع سيرفرات Netcup في **نفس الموقع الجغرافي** (مثلاً Nürnberg). |
| **Contabo** | من لوحة التحكم → "Private Networking" → إضافة السيرفرات لنفس الشبكة | Contabo يوفر شبكة خاصة مجانية. اختر جميع سيرفرات Contabo في **نفس الموقع** (مثلاً EU-Germany). |
### الربط بين الشركتين (Netcup ↔ Contabo):
> [!WARNING]
> سيرفرات Netcup وسيرفرات Contabo في مراكز بيانات مختلفة فيزيائياً، لذلك **لا يمكن وضعها في نفس الـ VLAN**. الحل:
| الطريقة | التفصيل |
| :--- | :--- |
| **WireGuard VPN Tunnel** | إنشاء نفق VPN مشفّر بين سيرفر من Netcup وسيرفر من Contabo. هذا يجعلها تتصرف كأنها في نفس الشبكة الداخلية مع تشفير كامل. زمن الاتصال بين مراكز بيانات ألمانيا ≈ 1-3ms فقط. |
| **التطبيق:** | تثبيت WireGuard على موزع الأحمال (Netcup) وعلى خوادم الـ API (Contabo)، وإنشاء نفق بينهما. كل السيرفرات الأخرى تتصل عبر الشبكة الداخلية لشركتها. |
### قواعد الجدار الناري (Firewall Rules):
| السيرفر | المنافذ المفتوحة للإنترنت العام | المنافذ المفتوحة فقط للشبكة الداخلية |
| :--- | :---: | :---: |
| **موزع الأحمال** | 80, 443 (HTTP/HTTPS) | — |
| **سيرفر الموقع (Location)** | منفذ WSS المحدد | — |
| **سيرفر الرحلات (Ride)** | منفذ WSS المحدد | — |
| **Web Server A & B** | ❌ لا شيء | 80, 443 (يستقبل فقط من LB) |
| **MySQL Master & Replica** | ❌ لا شيء | 3306 (فقط من Web + Sockets) |
| **Redis Master & Replica** | ❌ لا شيء | 6379 (فقط من Web + Sockets) |
| **سيرفر المدفوعات** | ❌ لا شيء | المنفذ المحدد (فقط من Web) |
| **سيرفر الخرائط** | ❌ لا شيء | 5000, 8080 (فقط من Web) |
---
## ثامناً: التقييم النهائي
> [!TIP]
> ### الحكم العام: تصميم سليم ومتزن وجاهز للتنفيذ.
| السؤال | الإجابة |
| :--- | :--- |
| **هل التنظيم سليم؟** | نعم. فصل المسؤوليات واضح: API منفصل، DB منفصل، Sockets منفصل، Redis منفصل، Maps منفصل. كل مكوّن يمكن ترقيته أو استبداله بشكل مستقل دون التأثير على البقية. |
| **هل الموارد كافية؟** | نعم وزيادة. هذه البنية تخدم حتى 15,000 سائق و8,000 راكب متصلين في نفس اللحظة، و40,000 رحلة يومياً. أكبر من حاجة السوق السوري والمصري في المرحلة الحالية. |
| **كم عدد السيرفرات؟** | **12 سيرفر** موزعة بين 9 سيرفرات Netcup و3 سيرفرات Contabo. |
| **كم التكلفة الشهرية؟** | **€104.39 يورو = $117.97 دولار أمريكي شهرياً** |
| **هل نحتاج شبكة داخلية؟** | **إلزامية بشكل قاطع.** بدونها قاعدة البيانات و Redis مكشوفان على الإنترنت. الشبكة الداخلية مجانية من كلا الشركتين، ويتم ربطهما ببعض عبر WireGuard VPN. |