finsh
هذا الالتزام موجود في:
259
task4-scalability/calculations.md
Normal file
259
task4-scalability/calculations.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# Task 4 — Scalability & Load Distribution (15,000 Requests/Second)
|
||||
|
||||
## Overview
|
||||
|
||||
This document proposes a scalable architecture for deploying an application on **Ghaymah Cloud** capable of handling **15,000 HTTP requests per second** while maintaining high availability, fault tolerance, and low response latency.
|
||||
|
||||
---
|
||||
|
||||
# 1. High-Level Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
|
||||
Users[Users]
|
||||
|
||||
Users --> DNS[Ghaymah DNS / Edge]
|
||||
|
||||
DNS --> LB[Load Balancer]
|
||||
|
||||
LB --> A1[Container 1]
|
||||
LB --> A2[Container 2]
|
||||
LB --> A3[Container 3]
|
||||
LB --> A4[...]
|
||||
LB --> A39[Container 39]
|
||||
|
||||
A1 --> Redis[(Redis Cache)]
|
||||
A2 --> Redis
|
||||
A3 --> Redis
|
||||
A39 --> Redis
|
||||
|
||||
Redis --> DB[(Primary Database)]
|
||||
|
||||
DB --> Storage[(Ghaymah Block Storage)]
|
||||
|
||||
subgraph AutoScaling
|
||||
Metrics[CPU • Memory • RPS]
|
||||
Decision{Scale?}
|
||||
ScaleOut[Add Containers]
|
||||
ScaleIn[Remove Containers]
|
||||
|
||||
Metrics --> Decision
|
||||
Decision -->|High Load| ScaleOut
|
||||
Decision -->|Low Load| ScaleIn
|
||||
end
|
||||
|
||||
LB -. Metrics .-> Metrics
|
||||
ScaleOut -. Register New Instances .-> LB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 2. Capacity Calculation
|
||||
|
||||
### Given
|
||||
|
||||
- Expected traffic = **15,000 requests/second**
|
||||
- One container capacity = **500 requests/second**
|
||||
|
||||
### Required Containers
|
||||
|
||||
```
|
||||
15,000 / 500 = 30 Containers
|
||||
```
|
||||
|
||||
To avoid saturation during sudden traffic spikes or node failures, a **30% safety margin** is added.
|
||||
|
||||
```
|
||||
30 × 1.30 = 39 Containers
|
||||
```
|
||||
|
||||
## Final Capacity
|
||||
|
||||
| Item | Value |
|
||||
|-------|------:|
|
||||
| Target Load | 15,000 req/s |
|
||||
| Capacity per Container | 500 req/s |
|
||||
| Base Containers | 30 |
|
||||
| Safety Margin | 30% |
|
||||
| Recommended Maximum | **39 Containers** |
|
||||
|
||||
---
|
||||
|
||||
# 3. Auto Scaling Policy
|
||||
|
||||
Recommended configuration:
|
||||
|
||||
```yaml
|
||||
min_replicas: 12
|
||||
max_replicas: 39
|
||||
|
||||
target_cpu: 65%
|
||||
target_memory: 70%
|
||||
|
||||
target_requests_per_container: 400
|
||||
|
||||
scale_up:
|
||||
increase: 4 containers
|
||||
cooldown: 60s
|
||||
|
||||
scale_down:
|
||||
decrease: 2 containers
|
||||
cooldown: 300s
|
||||
```
|
||||
|
||||
### Scaling Rules
|
||||
|
||||
Scale Out when:
|
||||
|
||||
- CPU > 65%
|
||||
- Memory > 70%
|
||||
- Average Requests > 400 req/s per container
|
||||
|
||||
Scale In when:
|
||||
|
||||
- CPU < 35%
|
||||
- Memory < 40%
|
||||
- Traffic remains low for 5 minutes
|
||||
|
||||
This policy minimizes unnecessary scaling operations while maintaining performance.
|
||||
|
||||
---
|
||||
|
||||
# 4. Cold Start Strategy
|
||||
|
||||
Launching new containers requires image download, application startup, and service initialization.
|
||||
|
||||
To reduce startup latency:
|
||||
|
||||
### 1. Readiness Probe
|
||||
|
||||
New containers receive traffic **only after** passing repeated `/health` checks.
|
||||
|
||||
Example:
|
||||
|
||||
- Interval: 5 seconds
|
||||
- Success Threshold: 3
|
||||
|
||||
---
|
||||
|
||||
### 2. Pre-Warmed Containers
|
||||
|
||||
Keep a minimum of **12 running replicas** to absorb sudden traffic spikes without waiting for new containers to start.
|
||||
|
||||
---
|
||||
|
||||
### 3. Lightweight Docker Images
|
||||
|
||||
Use slim base images such as:
|
||||
|
||||
```text
|
||||
python:3.11-slim
|
||||
```
|
||||
|
||||
Smaller images reduce image pull time significantly.
|
||||
|
||||
---
|
||||
|
||||
### 4. Predictive Scaling
|
||||
|
||||
Scale based on traffic trends rather than waiting until CPU reaches its maximum threshold.
|
||||
|
||||
---
|
||||
|
||||
### 5. Connection Draining
|
||||
|
||||
Before terminating a container:
|
||||
|
||||
- Stop accepting new requests.
|
||||
- Finish active requests.
|
||||
- Remove the container gracefully.
|
||||
|
||||
This prevents user-facing errors during scale-down.
|
||||
|
||||
---
|
||||
|
||||
# 5. Load Balancing Strategy
|
||||
|
||||
The Load Balancer should distribute requests evenly across all healthy containers.
|
||||
|
||||
Recommended algorithm:
|
||||
|
||||
- Round Robin
|
||||
- Least Connections (preferred for variable workloads)
|
||||
|
||||
Health checks should continuously monitor:
|
||||
|
||||
- `/health`
|
||||
- Container availability
|
||||
- Response latency
|
||||
|
||||
Unhealthy containers should automatically be removed from rotation.
|
||||
|
||||
---
|
||||
|
||||
# 6. High Availability
|
||||
|
||||
To improve reliability:
|
||||
|
||||
- Deploy multiple container replicas.
|
||||
- Eliminate single points of failure.
|
||||
- Automatically replace unhealthy containers.
|
||||
- Use horizontal scaling instead of vertical scaling.
|
||||
- Keep the application stateless whenever possible.
|
||||
|
||||
---
|
||||
|
||||
# 7. Using Ghaymah Block Storage
|
||||
|
||||
The application layer remains **stateless**, allowing containers to be created or removed without affecting user requests.
|
||||
|
||||
Persistent storage is required for:
|
||||
|
||||
- User uploads
|
||||
- Database storage
|
||||
- Persistent logs
|
||||
- Queue data
|
||||
- Shared application files
|
||||
|
||||
Ghaymah Block Storage provides durable volumes that remain available even if containers are recreated.
|
||||
|
||||
Benefits include:
|
||||
|
||||
- Persistent data
|
||||
- Easy attachment to new containers
|
||||
- Independent lifecycle from application containers
|
||||
- Simplified disaster recovery
|
||||
|
||||
---
|
||||
|
||||
# 8. Design Summary
|
||||
|
||||
| Component | Purpose |
|
||||
|-----------|---------|
|
||||
| Ghaymah DNS | Entry point |
|
||||
| Load Balancer | Traffic distribution |
|
||||
| 39 Containers | Handle application traffic |
|
||||
| Redis Cache | Reduce database load |
|
||||
| Primary Database | Persistent data |
|
||||
| Ghaymah Block Storage | Durable storage |
|
||||
| Auto Scaling | Automatic scaling |
|
||||
| Health Checks | Availability monitoring |
|
||||
|
||||
---
|
||||
|
||||
# Conclusion
|
||||
|
||||
The proposed architecture can reliably handle **15,000 requests per second** using horizontal scaling on Ghaymah Cloud.
|
||||
|
||||
Key design principles include:
|
||||
|
||||
- Horizontal scalability
|
||||
- Automatic load balancing
|
||||
- Redis caching
|
||||
- Health checks
|
||||
- Automatic scaling
|
||||
- Graceful container lifecycle
|
||||
- Persistent storage using Ghaymah Block Storage
|
||||
|
||||
This architecture delivers high availability, fault tolerance, and consistent performance under heavy production workloads.
|
||||
@@ -1,113 +0,0 @@
|
||||
# المهمة 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 مباشرة — فقط الطبقات الخلفية
|
||||
(قاعدة البيانات، تخزين الملفات) هي من تحتاجه، مما يسمح للطبقة الأمامية
|
||||
بالتوسع والتقلص بحرية دون القلق على فقدان بيانات.
|
||||
المرجع في مشكلة جديدة
حظر مستخدم