Bandwidth: ingress vs egress
- Ingress (inbound) -- что прилетает в ваш DC. Обычно дёшево или бесплатно (AWS: $0).
- Egress (outbound) -- что улетает к клиентам. Дорого (AWS: $0.09/GB в интернет).
Правило: egress стоит в 5-20 раз дороже storage. 1 TB egress в месяц = $90 (AWS). 10 TB = $900.
Типичные bandwidth источники
Клиент ←── Egress (API response, static files) ──── Сервер
──→ Ingress (request, uploads) ───────────→
Server-to-server (внутри DC): бесплатно в пределах AZ
Cross-AZ внутри региона: $0.01/GB
Cross-region: $0.02/GB
В интернет (public): $0.09/GB (первый TB), дешевле с объёмом
CDN offload
CDN перехватывает 80-99% запросов к статическому контенту. Это радикально снижает bandwidth cost.
Без CDN: Клиент → Ваш сервер (100% egress)
С CDN (hit 95%): Клиент → CDN edge → Ваш сервер (5% egress)
Cost эффект
| Сценарий | Egress от вас | CDN cost | Итого |
|---|---|---|---|
| Without CDN | 100 TB × $0.09 = $9 000 | $0 | $9 000 |
| With CDN (95% hit) | 5 TB × $0.09 = $450 | 100 TB × $0.02 = $2 000 | $2 450 |
Экономия 73% + быстрее клиенту.
Что хорошо cacheable
| Контент | Hit ratio |
|---|---|
| Images, videos, CSS/JS | 95-99% |
| HTML (static pages) | 80-95% |
| API responses (public, TTL 60s) | 50-80% |
| User-specific API | 0-20% |
Базовая формула bandwidth
Bandwidth (bytes/sec) = QPS × average_response_size
Пример: 3 000 RPS × 50 KB response = 150 MB/sec = 1.2 Gbps.
Для сравнения: 1 Gbps Ethernet пропускает 125 MB/s. Значит, одного гигабита мало -- нужен 10 Gbps uplink или CDN.
Типичные размеры ответов
| Тип ответа | Размер |
|---|---|
| JSON API (small) | 1-5 KB |
| JSON API (средний, с pagination) | 20-100 KB |
| HTML page (compressed) | 50-200 KB |
| HTML + inline CSS/JS | 500 KB - 2 MB |
| Image (avatar) | 10-30 KB |
| Image (photo) | 200 KB - 2 MB |
| Video chunk (HLS) | 1-5 MB |
RAM sizing для кэша
Главный вопрос: сколько надо RAM для кэша, чтобы покрыть X% запросов?
Правило Парето: 80/20
Для большинства consumer-сервисов 20% объектов генерируют 80% запросов. Ещё более жёстко: 5% объектов -- 50% трафика (Zipf distribution).
Формула working set
Working set = total_objects × hot_percentage × avg_size
Пример (social feed):
- 100M users
- 20% активны daily = 20M hot users
- avg timeline data = 100 KB
- working set = 20M × 100 KB = 2 TB
2 TB в одну ноду не положить. Но если цель -- покрыть 80% запросов, надо только top 20% hot users = 400 GB. Это 2-3 Redis ноды r5.12xlarge (384 GB RAM).
Cache hit ratio target
| Hit ratio | RAM | Эффект |
|---|---|---|
| 50% | 10% от working set | Снижает DB load на 50% |
| 80% | 20% от working set | Снижает DB load на 80% |
| 95% | 50% от working set | Снижает DB load на 95% |
| 99% | 80% от working set | DB почти простаивает |
Sweet spot -- 90-95%. Последние 5% cost exponentially.
AWS instance types для backend
Запомните pattern: буква = семейство, цифра = поколение.
| Instance | vCPU | RAM | Network | Use case |
|---|---|---|---|---|
| t3.medium | 2 | 4 GB | Up to 5 Gbps | Dev, мелкие сервисы |
| m5.xlarge | 4 | 16 GB | Up to 10 Gbps | General-purpose API |
| m5.4xlarge | 16 | 64 GB | Up to 10 Gbps | Heavy API |
| c5.2xlarge | 8 | 16 GB | Up to 10 Gbps | CPU-bound (encode, ML) |
| r5.xlarge | 4 | 32 GB | Up to 10 Gbps | Redis/cache small |
| r5.4xlarge | 16 | 128 GB | Up to 10 Gbps | Postgres primary |
| r5.12xlarge | 48 | 384 GB | 12 Gbps | Large cache node |
| x1e.32xlarge | 128 | 3.9 TB | 25 Gbps | In-memory DB (SAP HANA) |
| i3.4xlarge | 16 | 122 GB + 3.8 TB NVMe | 10 Gbps | Local NVMe (Cassandra) |
Rule of thumb:
- API server: m5.xlarge (4 vCPU, 16 GB) -- держит 2-5k RPS для Go, 500-1500 для PHP
- Postgres: r5.2xlarge-r5.4xlarge для medium load
- Redis: r5.xlarge-r5.12xlarge по working set
- Load balancer: не нужен, используйте ALB/NLB (managed)
Network limits
1 Gbps vs 10 Gbps vs 25 Gbps
| Link | MB/s | Response 50 KB | Response 500 KB |
|---|---|---|---|
| 1 Gbps | 125 | 2 500 RPS | 250 RPS |
| 10 Gbps | 1 250 | 25 000 RPS | 2 500 RPS |
| 25 Gbps | 3 125 | 62 500 RPS | 6 250 RPS |
Практика. Для API servers 10 Gbps хватает на 10-20k RPS. Если упираетесь -- чаще проблема в CPU/DB, не в network.
Intra-DC vs cross-DC
| Ссылка | Bandwidth | Latency | Cost |
|---|---|---|---|
| Same host (loopback) | 100+ GB/s | < 50 µs | $0 |
| Same rack | 10-25 Gbps | 0.1-0.5 ms | $0 |
| Same AZ | 10 Gbps | 0.5-1 ms | $0 |
| Cross-AZ | 10 Gbps | 1-2 ms | $0.01/GB |
| Cross-region | 10 Gbps | 60-150 ms | $0.02/GB |
| Public internet | limited by ISP | 10-200 ms | $0.09/GB egress |
Worked пример: видеостриминг
Сервис на 1M concurrent viewers, 1080p HD (5 Mbps per stream).
Peak bandwidth
Total bandwidth = 1M × 5 Mbps = 5 Tbps
5 Tbps = 5 × 10^12 / 8 = 625 GB/s
Cost без CDN (невозможно)
Ежедневно (прогрев 6 часов): 625 GB/s × 3600 × 6 = 13.5 PB/day
Egress cost: 13.5 PB × $90/TB = $1.2M/day
Ежемесячно: ~$36M
С CDN (offload 99.5%)
Egress от origin: 13.5 PB × 0.005 = 67.5 TB/day → $6k/day
CDN cost: 13.5 PB × $0.01/GB = $135k/day
Total: ~$4M/month
Даже с CDN видео -- дорого. Поэтому YouTube строит свои CDN (Google Edge), Netflix использует Open Connect.
Storage для контента
1080p фильм, 2 часа = ~5-7 GB
VOD каталог 10k фильмов = 10k × 6 GB = 60 TB
Adaptive bitrate (5 качеств) = 60 × 3 = 180 TB
С replication: 540 TB
Калькулятор bandwidth + memory
<?php
declare(strict_types=1);
/**
* Bandwidth and memory sizing helpers.
*/
final class NetworkSizing
{
/**
* Compute outbound bandwidth in bytes/sec for API traffic.
*/
public static function egressBytesPerSec(int $qps, int $avgResponseBytes): int
{
return $qps * $avgResponseBytes;
}
/**
* Monthly egress cost in USD.
* Default AWS rate: $0.09/GB for first 10TB, averaged for simplicity.
*/
public static function monthlyEgressCost(
int $qps,
int $avgResponseBytes,
float $cdnHitRatio = 0.0,
float $costPerGb = 0.09,
): float {
$secondsPerMonth = 30 * 86_400;
$totalBytes = $qps * $avgResponseBytes * $secondsPerMonth;
$originBytes = $totalBytes * (1 - $cdnHitRatio);
$gb = $originBytes / (1024 ** 3);
return round($gb * $costPerGb, 2);
}
/**
* Gbps needed for given QPS/response size.
*/
public static function requiredGbps(int $qps, int $avgResponseBytes): float
{
$bitsPerSec = $qps * $avgResponseBytes * 8;
return round($bitsPerSec / 1e9, 2);
}
}
/**
* Cache sizing via Pareto / working set.
*/
final class CacheSizing
{
/**
* Estimate RAM needed to achieve target hit ratio under Zipf distribution.
* Approximation: hit_ratio ≈ cache_share ^ 0.3 (heavy Zipf alpha ~0.8).
*/
public static function ramForHitRatio(
int $totalObjects,
int $avgObjectBytes,
float $targetHitRatio = 0.9,
): int {
// Inverse of approximation: share = hit_ratio ^ (1/0.3)
$cacheShare = $targetHitRatio ** (1 / 0.3);
$cachedObjects = (int) ($totalObjects * $cacheShare);
return $cachedObjects * $avgObjectBytes;
}
/**
* Working set = hot objects × size.
*/
public static function workingSetBytes(
int $totalObjects,
float $hotShare,
int $avgObjectBytes,
): int {
return (int) ($totalObjects * $hotShare * $avgObjectBytes);
}
}
// Usage:
// NetworkSizing::requiredGbps(3000, 50*1024) => 1.23 (Gbps)
// CacheSizing::ramForHitRatio(100_000_000, 1024, 0.9) => ~700 GB
- Bandwidth:
QPS × avg_response_size × 8 = bits/sec. Сравните с uplink (1/10/25 Gbps). - Egress cost: умножьте на секунды в месяце и на $0.09/GB (AWS public internet).
- CDN candidate? Если ratio cacheable > 80% -- обязательно CDN.
- Working set:
hot_objects × avg_size. Положите в RAM (Redis cluster). - Instance type: по RAM выбирайте r-family, по CPU -- c-family, универсально -- m-family.
- Growth: x2 per year -- закладывайте сразу.
Частые ошибки
- Забыть egress cost. Storage $20/TB/month, egress $90/TB. Разница 4.5x.
- Считать RAM по total data. Working set меньше total в 5-20 раз. Кэшируйте только hot.
- Не использовать CDN. 100 TB egress direct = $9k/month. С CDN = $2k/month.
- Cross-AZ для hot path. Межзональный трафик стоит $0.01/GB, легко добавляет $1000/месяц.
Выводы
- 1 Gbps = 125 MB/s. 10 Gbps = 1.25 GB/s. Формула bandwidth: QPS × response_size × 8.
- Egress дорог: $0.09/GB в интернет, используйте CDN для всего cacheable
- Working set = 20% от total (Pareto). Cache hit 90% достижим с 20-30% RAM от full.
- Instance types: m5 general, c5 CPU-bound, r5 memory-bound (Redis/Postgres)
- Video streaming -- самая bandwidth-тяжёлая задача: CDN не опция, а обязательность