MidТеория4 min

CDN, Proxy и Load Balancer

CDN, Reverse Proxy, Forward Proxy и балансировка нагрузки на сетевом уровне: архитектура, алгоритмы и практический выбор

Обзор

Между клиентом и сервером обычно находится несколько промежуточных компонентов, каждый из которых решает свою задачу: кеширование, безопасность, балансировка, маршрутизация.

┌────────┐     ┌─────────┐     ┌───────────┐     ┌──────────┐     ┌────────┐
│ Клиент ├────►│ Forward ├────►│    CDN    ├────►│ Reverse  ├────►│Backend │
│        │     │  Proxy  │     │  (Edge)   │     │  Proxy   │     │Server  │
│        │     │(корпор.)│     │           │     │  / LB    │     │        │
└────────┘     └─────────┘     └───────────┘     └──────────┘     └────────┘
  Браузер       Опционально    Ближайшая точка   Точка входа     Приложение
                               присутствия       в дата-центр

Зачем знать для System Design

  • CDN -- ключевой компонент для снижения латентности глобальных сервисов
  • Reverse proxy и LB -- обязательные элементы любой production-архитектуры
  • На собеседовании: «Как обеспечить низкую латентность для пользователей по всему миру?»

Forward Proxy

Что такое Forward Proxy

Forward proxy -- посредник, действующий от имени клиента. Клиент знает о прокси и направляет через него запросы.

Без прокси:
  Клиент ──────────────────────► Сервер
  (сервер видит IP клиента)

С Forward Proxy:
  Клиент ──► Forward Proxy ──► Сервер
  (сервер видит IP прокси, не клиента)

Применения

Применение Описание
Корпоративный контроль Блокировка нежелательных сайтов
Анонимность Скрытие IP клиента (VPN, Tor)
Кеширование Кеш частых запросов (Squid)
Обход ограничений Доступ к заблокированным ресурсам
Логирование Аудит интернет-активности

Пример: корпоративный прокси

┌─────────────┐
│ Сотрудник A ├──┐
└─────────────┘  │     ┌──────────────┐     ┌──────────────┐
                 ├────►│ Squid Proxy  ├────►│  Интернет    │
┌─────────────┐  │     │              │     │              │
│ Сотрудник B ├──┘     │ • Кеш        │     │ example.com  │
└─────────────┘        │ • Фильтрация │     │ blocked.com ✗│
                       │ • Логирование│     └──────────────┘
                       └──────────────┘

Reverse Proxy

Что такое Reverse Proxy

Reverse proxy -- посредник, действующий от имени сервера. Клиент не знает о backend-серверах и обращается к прокси.

Forward Proxy:                     Reverse Proxy:
Клиент знает о прокси              Клиент не знает о backend

Клиент ──► [FP] ──► Сервер        Клиент ──► [RP] ──► Backend 1
  ↑ Настроен клиентом               ↑ Настроен сервером │
                                                        ├──► Backend 2
                                                        └──► Backend 3

Функции Reverse Proxy

┌────────────────────────────────────────────────────────┐
│                   Reverse Proxy                        │
│                                                        │
│  ┌────────────┐ ┌─────────────┐ ┌───────────────────┐ │
│  │  TLS       │ │ Compression │ │  Rate Limiting    │ │
│  │Termination │ │ (gzip, br)  │ │  (защита от DDoS) │ │
│  └────────────┘ └─────────────┘ └───────────────────┘ │
│  ┌────────────┐ ┌─────────────┐ ┌───────────────────┐ │
│  │  Caching   │ │ URL Rewrite │ │  Authentication   │ │
│  │ (статика)  │ │ / Routing   │ │  (OAuth, JWT)     │ │
│  └────────────┘ └─────────────┘ └───────────────────┘ │
│  ┌────────────┐ ┌─────────────┐ ┌───────────────────┐ │
│  │   Load     │ │    WAF      │ │  Request/Response │ │
│  │ Balancing  │ │ (firewall)  │ │  Transformation   │ │
│  └────────────┘ └─────────────┘ └───────────────────┘ │
└────────────────────────────────────────────────────────┘

Популярные Reverse Proxy

Инструмент Особенности Применение
Nginx Высокая производительность, event-driven Веб-серверы, API gateway
HAProxy Лучший для L4/L7 балансировки Высоконагруженные системы
Envoy Service mesh, gRPC, observability Kubernetes, Istio
Traefik Автоматическая конфигурация, Let's Encrypt Docker, Kubernetes
Caddy Автоматический HTTPS, простота Малые/средние проекты

Load Balancer

Уровни балансировки

┌───────────────────────────────────────────────────────┐
│           L4 Load Balancer (Transport)                │
│                                                       │
│  Работает с: TCP/UDP пакетами                        │
│  Видит: IP-адреса, порты                             │
│  Не видит: HTTP-заголовки, cookies, URL              │
│  Скорость: Очень высокая (~миллионы conn/sec)        │
│  Примеры: AWS NLB, LVS, IPVS                        │
└───────────────────────────────────────────────────────┘

┌───────────────────────────────────────────────────────┐
│           L7 Load Balancer (Application)              │
│                                                       │
│  Работает с: HTTP-запросами                          │
│  Видит: URL, заголовки, cookies, тело запроса        │
│  Может: content-based routing, SSL termination       │
│  Скорость: Ниже (~сотни тысяч req/sec)              │
│  Примеры: AWS ALB, Nginx, HAProxy, Envoy            │
└───────────────────────────────────────────────────────┘

Сравнение L4 vs L7

Критерий L4 (Transport) L7 (Application)
Что видит IP, порт URL, заголовки, cookie
TLS Passthrough или termination Termination
Routing IP:port → backend URL path, host, headers
WebSocket Прозрачно Нужна поддержка Upgrade
Производительность Миллионы conn/sec Сотни тысяч req/sec
Health checks TCP SYN/ACK HTTP GET /health
Session affinity IP hash Cookie-based
Стоимость Ниже Выше

Алгоритмы балансировки

Round Robin

Запросы распределяются по кругу:

Запрос 1 ──► Server A
Запрос 2 ──► Server B
Запрос 3 ──► Server C
Запрос 4 ──► Server A  (по кругу)
Запрос 5 ──► Server B
...

Плюсы: простой, равномерный
Минусы: не учитывает нагрузку серверов

Weighted Round Robin

Server A (weight=5): получает 5 из 10 запросов (50%)
Server B (weight=3): получает 3 из 10 запросов (30%)
Server C (weight=2): получает 2 из 10 запросов (20%)

Применение: серверы с разной мощностью, canary deployment

Least Connections

Запрос направляется на сервер с наименьшим числом активных соединений:

Server A: 12 connections ─┐
Server B: 5 connections  ─┼── Запрос → Server C (минимум)
Server C: 3 connections  ─┘

Плюсы: адаптивный, учитывает реальную нагрузку
Применение: запросы с разным временем обработки

IP Hash

hash(client_ip) % num_servers = server_index

Client 192.168.1.1 → hash → Server A (всегда)
Client 192.168.1.2 → hash → Server C (всегда)
Client 192.168.1.3 → hash → Server B (всегда)

Плюсы: session affinity без cookies
Минусы: неравномерность при малом числе клиентов, проблемы с NAT

Consistent Hashing

              0°
              │
      ┌───────┴───────┐
    S3 │               │ S1
      │   Hash Ring    │
      │               │
    S2 │               │
      └───────┬───────┘
              │
             180°

Ключ K1 → хеш → попадает в зону S1
Ключ K2 → хеш → попадает в зону S2

При добавлении S4: перераспределяется только ~1/N ключей
При удалении S2: ключи S2 переходят к следующему серверу (S3)

Применение: кеширование, шардирование, CDN

Least Response Time

Запрос направляется на сервер с минимальным временем ответа:

Server A: avg 45ms  ─┐
Server B: avg 12ms  ─┼── Запрос → Server B (быстрейший)
Server C: avg 78ms  ─┘

Плюсы: оптимизация латентности
Минусы: нужен мониторинг, может быть нестабильным

Health Checks

Passive (наблюдение):
  LB отслеживает ответы backend
  5xx ответов > порога → сервер помечен unhealthy

Active (опрос):
  LB периодически отправляет проверочные запросы

  LB ── GET /health ──► Server A ── 200 OK ✓
  LB ── GET /health ──► Server B ── 200 OK ✓
  LB ── GET /health ──► Server C ── timeout ✗ → Убрать из ротации

  interval: 10 сек
  threshold: 3 неудачи → unhealthy
  recovery: 2 успеха → healthy

Пример конфигурации

# Nginx upstream with health checks and weights
upstream api_backend {
    least_conn;                           # Algorithm

    server 10.0.1.1:8080 weight=5;       # Primary (more powerful)
    server 10.0.1.2:8080 weight=3;       # Secondary
    server 10.0.1.3:8080 weight=2;       # Tertiary
    server 10.0.1.4:8080 backup;         # Backup (only if all down)

    keepalive 32;                         # Connection pooling
}

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # TLS termination
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    location /api/ {
        proxy_pass http://api_backend;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;

        # Timeouts
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
    }

    location /static/ {
        # Serve static files directly
        root /var/www;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

CDN (Content Delivery Network)

Что такое CDN

CDN -- распределённая сеть серверов (Edge/PoP), кеширующих контент ближе к пользователю.

Без CDN:
  Пользователь (Москва) ──── 150ms ────► Origin (Вирджиния)
  Пользователь (Токио)  ──── 200ms ────► Origin (Вирджиния)

С CDN:
  Пользователь (Москва) ──── 10ms ─────► PoP (Москва)
  Пользователь (Токио)  ──── 5ms  ─────► PoP (Токио)
                                           │ cache miss?
                                           └── 150ms → Origin

Архитектура CDN

                    ┌──────────────────┐
                    │   Origin Server  │
                    │  (ваш сервер)    │
                    └────────┬─────────┘
                             │
              ┌──────────────┼──────────────┐
              │              │              │
        ┌─────▼──────┐ ┌────▼───────┐ ┌────▼───────┐
        │ Shield/Mid │ │  Shield    │ │  Shield    │
        │ (US-East)  │ │ (EU-West)  │ │ (AP-East)  │
        └─────┬──────┘ └────┬───────┘ └────┬───────┘
              │              │              │
        ┌─────┼───┐    ┌────┼───┐    ┌─────┼───┐
        │     │   │    │    │   │    │     │   │
      ┌─▼─┐┌─▼─┐┌▼┐ ┌─▼─┐┌─▼─┐┌▼┐ ┌─▼──┐┌─▼─┐┌▼┐
      │NYC││BOS││DC│ │LDN││AMS││FR│ │TKY ││SEL││SG│
      │PoP││PoP││Po│ │PoP││PoP││Po│ │PoP ││PoP││Po│
      └───┘└───┘└──┘ └───┘└───┘└──┘ └────┘└───┘└──┘
       Edge Points of Presence (PoPs)

Как работает CDN

1. Пользователь запрашивает: https://static.example.com/image.jpg

2. DNS резолвит static.example.com → IP ближайшего PoP (Anycast)

3. PoP проверяет кеш:

   Cache HIT:                          Cache MISS:
   PoP ── image.jpg ──► Пользователь   PoP ── GET /image.jpg ──► Origin
   (~5 мс)                              PoP ◄── image.jpg ────── Origin
                                         PoP кеширует + отдаёт пользователю
                                         (~150 мс первый запрос)

4. Заголовки кеширования:
   Cache-Control: public, max-age=86400
   CDN-Cache-Control: max-age=604800
   Vary: Accept-Encoding

Что кешировать на CDN

Контент Кешировать? TTL Заголовок
Статика (JS, CSS, изображения) Да Долго (1 год) Cache-Control: public, max-age=31536000, immutable
API-ответы (публичные) Да Короткий (60с) Cache-Control: public, max-age=60, s-maxage=300
API-ответы (персональные) Нет - Cache-Control: private, no-store
HTML (SSR) Возможно Короткий (60с) Cache-Control: public, s-maxage=60, stale-while-revalidate=300
Видео/аудио Да Долго Cache-Control: public, max-age=604800

Инвалидация кеша CDN

Стратегия 1: Хеш в имени файла (рекомендуется)
  /assets/app.a1b2c3d4.js  → Новая сборка = новый хеш = новый URL
  Старый файл всё ещё в кеше, но никто его не запрашивает

Стратегия 2: Purge API
  curl -X POST https://api.cloudflare.com/purge \
    -d '{"files": ["https://example.com/style.css"]}'

Стратегия 3: Surrogate Keys (теги)
  Surrogate-Key: product-123 homepage
  Purge по тегу: все объекты с тегом "product-123"

Стратегия 4: stale-while-revalidate
  Cache-Control: max-age=60, stale-while-revalidate=300
  Отдаёт устаревший контент, пока обновляет в фоне

CDN провайдеры

Провайдер PoPs Особенности
Cloudflare 300+ WAF, DDoS, Workers (edge computing)
AWS CloudFront 450+ Интеграция с AWS, Lambda@Edge
Akamai 4000+ Enterprise, крупнейшая сеть
Fastly 80+ VCL, Instant Purge, Compute@Edge
Google Cloud CDN 140+ Интеграция с GCP

CDN для динамического контента

Современные CDN кешируют не только статику:

Edge Computing:
  ┌────────┐    ┌───────────────────┐    ┌────────┐
  │ Клиент ├───►│  Edge Worker      ├───►│ Origin │
  │        │    │                   │    │        │
  │        │    │  • A/B тесты      │    │        │
  │        │    │  • Персонализация │    │        │
  │        │    │  • Auth проверка  │    │        │
  │        │    │  • Геолокация     │    │        │
  │        │◄───┤  • Трансформация  │◄───┤        │
  └────────┘    └───────────────────┘    └────────┘

  Cloudflare Workers, AWS Lambda@Edge, Fastly Compute

Сравнительная таблица

Критерий Forward Proxy Reverse Proxy Load Balancer CDN
Действует от имени Клиента Сервера Сервера Сервера
Клиент знает? Да Нет Нет Нет
Основная задача Анонимность, фильтрация Безопасность, routing Распределение нагрузки Кеширование, латентность
Кеширование Да Да Нет Да (основная функция)
TLS Опционально Termination L4 passthrough / L7 term Edge termination
Масштаб Локальный Один дата-центр Один дата-центр Глобальный
Примеры Squid, Privoxy Nginx, Envoy HAProxy, AWS ALB/NLB Cloudflare, CloudFront

Архитектура production-системы

┌─────────┐     ┌───────────┐     ┌─────────────┐     ┌──────────┐
│ Клиент  ├────►│    CDN    ├────►│  L4 LB      ├────►│ L7 LB /  │
│         │     │(статика + │     │(TCP/UDP,    │     │ Reverse  │
│         │     │ edge)     │     │ высокая     │     │ Proxy    │
└─────────┘     └───────────┘     │ пропускная  │     │(routing, │
                                  │ способность)│     │ TLS)     │
                                  └─────────────┘     └────┬─────┘
                                                           │
                                          ┌────────────────┼────────────────┐
                                          │                │                │
                                    ┌─────▼────┐    ┌─────▼────┐    ┌─────▼────┐
                                    │ Backend  │    │ Backend  │    │ Backend  │
                                    │ Server 1 │    │ Server 2 │    │ Server 3 │
                                    └──────────┘    └──────────┘    └──────────┘

DNS + CDN + LB: полный путь запроса

1. Клиент вводит api.example.com
2. DNS (Route 53, GeoDNS) → IP ближайшего CDN PoP
3. CDN Edge:
   - Cache HIT → ответ клиенту (5 мс)
   - Cache MISS → запрос к Origin
4. L4 Load Balancer (NLB) → TCP → L7 Load Balancer (ALB)
5. L7 LB: TLS termination, routing по URL/headers
6. Backend обрабатывает запрос
7. Ответ возвращается клиенту, CDN кеширует (если можно)

Суммарная латентность:
  Cache HIT:  5-20 мс (CDN)
  Cache MISS: 50-200 мс (CDN → Origin → Backend)

Проверь себя

Чем L4 балансировщик отличается от L7?

Какой алгоритм балансировки лучше всего подходит, когда запросы имеют сильно различающееся время обработки?

Что такое CDN Shield (Origin Shield) и зачем он нужен?

Почему рекомендуется использовать хеш в имени файла (app.a1b2c3.js) вместо purge API для инвалидации кеша CDN?

В чём ключевое отличие Forward Proxy от Reverse Proxy?