feat: complete initial project structure for API and Monitoring Dashboards
هذا الالتزام موجود في:
22
architecture/block_storage.md
Normal file
22
architecture/block_storage.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Using ghaymah Block Storage for Stateful Workloads
|
||||
|
||||
Containers are inherently stateless; they lose their local filesystem data when they are destroyed or rescheduled. For applications that require persistent data (Stateful Workloads), we utilize **ghaymah Block Storage**.
|
||||
|
||||
## 1. What is Block Storage?
|
||||
Block Storage provides persistent, highly available disk volumes that can be attached to containers. Unlike object storage (S3), it behaves like a physical hard drive mounted to the OS.
|
||||
|
||||
## 2. Use Cases in our Architecture
|
||||
While our API application is mostly stateless, certain workloads require persistence:
|
||||
- **Local Caching:** If a container downloads large datasets or machine learning models upon startup, these can be stored on Block Storage so subsequent container restarts are faster.
|
||||
- **Session Data / Logs:** If we are writing complex audit logs that haven't yet been shipped to a centralized logging service.
|
||||
- **Databases:** If running a self-managed database (e.g., PostgreSQL or Redis) within a container, Block Storage is mandatory to prevent data loss.
|
||||
|
||||
## 3. Configuration & Mounting
|
||||
When deploying via the `ghaymah deploy` CLI or dashboard, we specify a volume mount:
|
||||
```yaml
|
||||
volumes:
|
||||
- name: my-persistent-data
|
||||
size: 50GB
|
||||
mountPath: /mnt/data
|
||||
```
|
||||
Inside the container, the application can simply read/write files to `/mnt/data/` knowing the data will survive container restarts.
|
||||
24
architecture/capacity.md
Normal file
24
architecture/capacity.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Capacity Planning: Handling 15,000 req/s
|
||||
|
||||
To ensure high availability and responsiveness under a load of 15,000 requests per second, we must calculate the required number of container instances.
|
||||
|
||||
## Base Assumptions
|
||||
- **Target Load:** 15,000 req/s
|
||||
- **Max Capacity per Container:** 500 req/s
|
||||
- **Safety Margin:** 30%
|
||||
|
||||
## Calculation
|
||||
1. **Effective Capacity per Container:**
|
||||
To maintain a 30% margin, we calculate the effective capacity each container should handle before we consider scaling out.
|
||||
`500 req/s * (1 - 0.30) = 350 req/s`
|
||||
|
||||
2. **Total Containers Required:**
|
||||
Divide the total expected load by the effective capacity per container.
|
||||
`15,000 req/s / 350 req/s per container ≈ 42.85`
|
||||
|
||||
3. **Rounding Up:**
|
||||
We cannot have a fraction of a container, so we always round up to the next whole number.
|
||||
`ceil(42.85) = 43 containers`
|
||||
|
||||
## Conclusion
|
||||
To safely handle 15,000 req/s while maintaining a 30% safety margin (which helps absorb sudden traffic spikes or the failure of a few containers), the auto-scaling group should be configured to maintain a baseline of **43 containers** during peak load.
|
||||
20
architecture/cold_start.md
Normal file
20
architecture/cold_start.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Cold Start Strategy
|
||||
|
||||
When auto-scaling responds to a traffic spike, new containers must be initialized. The time it takes from the scaling decision to the container actually serving requests is the "cold start" latency.
|
||||
|
||||
To minimize this delay and prevent dropped requests, we implement the following strategy:
|
||||
|
||||
## 1. Lightweight Base Images
|
||||
- Use Alpine or distroless base images (e.g., `python:3.11-alpine`).
|
||||
- Smaller images pull faster from the Container Registry over the network.
|
||||
|
||||
## 2. Pre-warming (Buffer Pool)
|
||||
- Configure the Auto-Scaling Group to always maintain a "buffer" of idle containers (e.g., 10% of the current required capacity).
|
||||
- If we need 43 containers for active load, we run ~47 containers. When traffic spikes, these 4 idle containers can serve requests instantly while the ASG provisions new ones.
|
||||
|
||||
## 3. Lazy Loading & Readiness Probes
|
||||
- Defer non-critical initialization (like building large in-memory caches) until *after* the container has started accepting requests.
|
||||
- Configure Kubernetes/ghaymah readiness probes to accurately reflect when the app is ready to serve traffic, ensuring the load balancer doesn't route traffic to a container that is still booting.
|
||||
|
||||
## 4. Keep-Alive & Connection Pooling
|
||||
- Ensure idle containers aren't prematurely terminated. Keep database connections alive in a connection pool to avoid the latency of establishing new TCP handshakes during a sudden burst.
|
||||
26
architecture/diagram.mmd
Normal file
26
architecture/diagram.mmd
Normal file
@@ -0,0 +1,26 @@
|
||||
```mermaid
|
||||
graph TD
|
||||
Client((Client Requests <br> 15,000 req/s)) --> WAF[Web Application Firewall]
|
||||
WAF --> LB[ghaymah Load Balancer]
|
||||
|
||||
subgraph Auto-Scaling Group
|
||||
direction LR
|
||||
LB -->|Traffic Distribution| API1[myapp-api Container 1 <br> ~350 req/s]
|
||||
LB --> API2[myapp-api Container 2 <br> ~350 req/s]
|
||||
LB --> API3[myapp-api Container 3]
|
||||
LB -.-> APIN[myapp-api Container N <br> Total: 43 Containers]
|
||||
end
|
||||
|
||||
API1 --> BS1[(ghaymah Block Storage <br> /mnt/data)]
|
||||
API2 --> BS2[(ghaymah Block Storage <br> /mnt/data)]
|
||||
API3 --> BS3[(ghaymah Block Storage <br> /mnt/data)]
|
||||
APIN --> BSN[(ghaymah Block Storage <br> /mnt/data)]
|
||||
|
||||
classDef container fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
|
||||
classDef lb fill:#fff3e0,stroke:#e65100,stroke-width:2px;
|
||||
classDef storage fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;
|
||||
|
||||
class API1,API2,API3,APIN container;
|
||||
class LB lb;
|
||||
class BS1,BS2,BS3,BSN storage;
|
||||
```
|
||||
المرجع في مشكلة جديدة
حظر مستخدم