Initial Ghaymah tasks setup
هذا الالتزام موجود في:
113
task4-scalability/scalability.md
Normal file
113
task4-scalability/scalability.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# المهمة 4 — قابلية التوسع وتوزيع الأحمال (15,000 req/s)
|
||||
|
||||
## 1) Architecture Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
U[المستخدمون] --> DNS[Ghaymah DNS / CDN Edge]
|
||||
DNS --> LB[Load Balancer<br/>غيمة]
|
||||
|
||||
LB --> C1[حاوية 1<br/>500 req/s]
|
||||
LB --> C2[حاوية 2<br/>500 req/s]
|
||||
LB --> C3[حاوية 3<br/>500 req/s]
|
||||
LB --> C4[...]
|
||||
LB --> C39[حاوية 39<br/>500 req/s]
|
||||
|
||||
C1 --> CACHE[(Redis Cache)]
|
||||
C2 --> CACHE
|
||||
C3 --> CACHE
|
||||
C39 --> CACHE
|
||||
|
||||
CACHE --> DB[(قاعدة بيانات رئيسية)]
|
||||
C1 --> BLOCK[(Ghaymah Block Storage<br/>للبيانات الدائمة)]
|
||||
C39 --> BLOCK
|
||||
|
||||
subgraph Autoscaler["Auto-scaling Controller"]
|
||||
METRICS[مقاييس CPU/Memory/RPS] --> DECIDE{تجاوز الحد؟}
|
||||
DECIDE -- نعم --> ADD[إضافة حاويات جديدة]
|
||||
DECIDE -- لا --> KEEP[إبقاء العدد الحالي]
|
||||
end
|
||||
|
||||
LB -. تقرير المقاييس .-> METRICS
|
||||
ADD -. توسيع .-> LB
|
||||
```
|
||||
|
||||
**الفكرة:** طلبات المستخدمين تصل أولاً لـ Load Balancer الذي يوزّعها على مجموعة
|
||||
حاويات متطابقة (horizontal scaling)، كل حاوية تتعامل مع الحمل الخاص بها وتتصل
|
||||
بطبقة cache مشتركة قبل قاعدة البيانات لتقليل الضغط عليها، بينما البيانات الدائمة
|
||||
(uploads, session files, ...) تُخزَّن على Ghaymah Block Storage القابل للربط
|
||||
بأي حاوية جديدة.
|
||||
|
||||
---
|
||||
|
||||
## 2) حساب عدد الحاويات المطلوبة
|
||||
|
||||
المعطيات:
|
||||
- الحمل المستهدف: **15,000 req/s**
|
||||
- سعة الحاوية الواحدة: **500 req/s**
|
||||
- هامش أمان: **30%** (لتفادي التشبع عند تذبذب الحمل أو فقدان حاوية)
|
||||
|
||||
**الحساب:**
|
||||
```
|
||||
عدد الحاويات الأساسي = 15,000 / 500 = 30 حاوية
|
||||
|
||||
مع هامش الأمان 30%:
|
||||
30 × 1.30 = 39 حاوية
|
||||
```
|
||||
|
||||
➡️ **العدد المطلوب فعلياً = 39 حاوية** (وليس 30)، بحيث لو سقطت بضع حاويات
|
||||
أو ارتفع الحمل مؤقتاً 20-30% فوق المتوقع، النظام لا يصل للتشبع الكامل.
|
||||
|
||||
**توصية عملية للإعداد:**
|
||||
```yaml
|
||||
min_replicas: 12 # يغطي حمل القاعدة العادي (ليس ذروة اليوم)
|
||||
max_replicas: 39 # يغطي ذروة 15,000 req/s + الهامش
|
||||
target_cpu: 65%
|
||||
target_rps_per_pod: 400 # هدف أقل من السعة القصوى (500) لإعطاء هامش استجابة
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3) استراتيجية Cold Start للحاويات الجديدة
|
||||
|
||||
المشكلة: حاوية جديدة تحتاج وقتاً (تحميل صورة، تهيئة التطبيق، اتصال بقاعدة
|
||||
البيانات) قبل أن تكون جاهزة فعلياً لاستقبال حمل — لو أرسل لها الـ LB طلبات
|
||||
فوراً ستفشل أو تبطئ الاستجابة.
|
||||
|
||||
الحل المقترح:
|
||||
1. **Readiness Probe صارم:** لا يُضاف الـ pod لقائمة الـ Load Balancer إلا
|
||||
بعد نجاح فحص `/health` عدة مرات متتالية (مثلاً 3 نجاحات متتالية كل 5 ثوانٍ).
|
||||
2. **Pre-warmed pool (نسخ دافئة جاهزة):** الاحتفاظ بعدد أدنى من الحاويات
|
||||
(`min_replicas`) يعمل باستمرار حتى في أوقات الحمل المنخفض، بدل الاعتماد
|
||||
بالكامل على scale-from-zero، لأن بدء التشغيل من الصفر أبطأ بكثير.
|
||||
2. **صور خفيفة (slim images):** استخدام صور أساس صغيرة (مثل `python:3.11-slim`)
|
||||
لتقليل وقت سحب الصورة (image pull time) عند جدولة حاوية جديدة على node جديد.
|
||||
3. **Predictive/Proactive scaling:** التوسع بناءً على اتجاه الحمل (trend)
|
||||
وليس فقط عندما يتجاوز الحمل الحد الحالي — مثال: لو الحمل يرتفع بمعدل ثابت
|
||||
خلال آخر دقيقتين، ابدأ بإضافة حاويات الآن بدل الانتظار حتى الوصول للحد الأقصى.
|
||||
4. **Connection draining عند الإزالة:** عند تقليص العدد (scale-down)، إعطاء
|
||||
الحاوية مهلة لإنهاء الطلبات الجارية قبل إيقافها فعلياً، لتفادي أخطاء للمستخدمين.
|
||||
|
||||
---
|
||||
|
||||
## 4) استخدام Ghaymah Block Storage لأحمال العمل ذات الحالة (Stateful)
|
||||
|
||||
التطبيق نفسه (API) عادة **stateless** — أي حاوية جديدة يمكن أن تخدم أي طلب
|
||||
دون الحاجة لبيانات محفوظة محلياً. لكن بعض المكونات تحتاج تخزيناً دائماً:
|
||||
|
||||
- **ملفات مرفوعة من المستخدمين** (صور، مستندات) يجب أن تبقى متاحة حتى لو
|
||||
تغيّرت الحاوية التي تخدم الطلب التالي.
|
||||
- **قواعد بيانات أو أنظمة queue** تحتاج تخزيناً لا يُفقد عند إعادة تشغيل الحاوية.
|
||||
- **ملفات cache دائمة أو logs** يُراد الاحتفاظ بها عبر إعادة الجدولة.
|
||||
|
||||
**كيف يُستخدم Ghaymah Block Storage هنا:**
|
||||
- يُربط (mount) كـ volume دائم لأي حاوية تحتاج تخزيناً (مثل خدمة قاعدة
|
||||
البيانات أو خدمة رفع الملفات)، بحيث تبقى البيانات موجودة حتى لو حُذفت
|
||||
الحاوية وأُعيد إنشاؤها من جديد على node مختلف.
|
||||
- يُفصل عن الحاويات نفسها (decoupled)، فيمكن لأي نسخة جديدة من الخدمة أن
|
||||
"ترث" نفس البيانات بمجرد إعادة ربط نفس الـ volume، بدل تخزين البيانات
|
||||
داخل الحاوية (وهو ما يفقد عند إعادة التشغيل).
|
||||
- بالنسبة للـ API نفسه (الطبقة الأمامية عالية التوسع من 39 حاوية)، يبقى
|
||||
**stateless تماماً** ولا يحتاج Block Storage مباشرة — فقط الطبقات الخلفية
|
||||
(قاعدة البيانات، تخزين الملفات) هي من تحتاجه، مما يسمح للطبقة الأمامية
|
||||
بالتوسع والتقلص بحرية دون القلق على فقدان بيانات.
|
||||
المرجع في مشكلة جديدة
حظر مستخدم