Компьютерные сети
Сети распределённых систем
В 2017 году Amazon S3 упал на 4 часа из-за typo в команде. Это затронуло половину интернета - Slack, Trello, IFTTT. Распределённые системы выглядят надёжнее, но их failure modes сложнее и коварнее.
- **GitHub** - partial outage когда часть git операций работает, часть нет
- **AWS S3** - 11 девяток durability, но availability outages случаются
- **Google Spanner** - globally distributed DB с CAP trade-offs
Предварительные знания
Network Partitions
**Network Partition (split-brain)** - ситуация, когда часть узлов системы не может связаться с другой частью. Оба сегмента работают, но не видят друг друга. Для распределённых систем это не edge case, а регулярная реальность.
Представь: datacenter в Москве и datacenter в Лондоне. Оба работают, но канал между ними временно недоступен. Каждый сегмент думает, что он единственный живой. Что делать? Продолжать работу (риск конфликтов) или остановиться (потеря доступности)?
**CAP теорема:** При network partition система может гарантировать либо Consistency (все узлы видят одинаковые данные), либо Availability (система отвечает на запросы). Нельзя иметь оба одновременно при partition.
**Как обнаружить partition?** Heartbeat между узлами. Если узел не отвечает на heartbeat за timeout - он считается недоступным. Проблема: timeout 5 секунд vs 30 секунд - баланс между false positives и временем обнаружения реальных проблем.
Что означает CAP теорема для распределённой системы при network partition?
Latency в распределённых системах
**Latency** в распределённых системах - не просто задержка сети. Это комбинация: network RTT + serialization + queuing + processing. И главное - latency имеет **распределение**, а не фиксированное значение.
Средняя latency 10ms ничего не говорит о worst case. p99 latency (99-й перцентиль) может быть 500ms. А p99.9 - 2 секунды. Для пользователей важны именно tail latencies.
**Fan-out amplification:** Если сервис делает 10 параллельных запросов, p99 финального ответа определяется самым медленным. 10 запросов с p99=100ms дают p99 финала ≈ 400ms (не 100ms!).
**Стратегии борьбы с tail latency:** • **Hedged requests** - отправь запрос на 2 сервера, верни первый ответ • **Timeouts** - не жди бесконечно, fail fast • **Circuit breaker** - если сервис деградирует, перестань его вызывать • **Load shedding** - отбрасывай лишнюю нагрузку до очереди
Если сервис делает 10 параллельных запросов с p99=100ms каждый, какой примерно будет p99 общего времени?
Partial Failures
**Partial Failure** - фундаментальное отличие распределённых систем от локальных. В локальной программе либо всё работает, либо процесс падает. В распределённой системе часть компонентов может работать, часть - нет, и ты не знаешь какие.
Отправил запрос, не получил ответа. Что случилось? Сервер упал? Сеть потеряла пакет? Сервер обработал запрос, но ответ потерялся? Сервер завис на 30 секунд и ответит позже? **Невозможно точно знать.**
**Идемпотентность - ключ к retry.** Если операция идемпотентна (повторное выполнение даёт тот же результат), можно безопасно retry. `GET /user/123` - идемпотентен. `POST /transfer?amount=100` - НЕ идемпотентен (без idempotency key).
**Стратегии обработки partial failures:** • **Retry with backoff** - повторяй с увеличивающейся задержкой • **Idempotency keys** - безопасный retry для non-idempotent операций • **Circuit breaker** - не retry к явно сломанному сервису • **Saga pattern** - компенсирующие транзакции для отмены частичных операций
Клиент отправил запрос на перевод денег и получил timeout. Что он точно знает?
Сетевые паттерны распределённых систем
**Распределённые системы используют сеть по-особому:** retries, timeouts, circuit breakers, service discovery. Это не просто HTTP запросы - это целая инфраструктура для reliable communication.
**Service Discovery** - как найти IP:port сервиса? Hardcode? DNS? Consul/etcd? В Kubernetes - CoreDNS + Service resources. В AWS - Cloud Map или ALB.
**Health checks в распределённых системах:** • **Liveness** - процесс жив? (restart если нет) • **Readiness** - готов принимать трафик? (убрать из load balancer) • **Startup** - завершилась инициализация? (не убивать раньше времени)
Timeout значит, что сервер упал
Timeout означает 'я не знаю что случилось' - сервер мог обработать запрос
В распределённой системе timeout может означать: потерю запроса, потерю ответа, медленный сервер, network partition. Без дополнительной проверки (query состояния, idempotency key) невозможно знать результат
Зачем добавлять jitter к exponential backoff при retry?
Итоги
- **Network Partition** - узлы работают, но не видят друг друга (CAP trade-off)
- **Latency distribution** - p99 важнее average; fan-out amplifies tail latency
- **Partial Failure** - часть системы может работать, часть нет, и это неизвестно
- **Idempotency** - ключ к безопасным retry при неизвестном состоянии
- **Resilience patterns** - retry + backoff + jitter, circuit breaker, bulkhead
Связанные темы
Понимание сетевых проблем - основа для изучения RPC и message queues:
- TCP Congestion — Congestion control влияет на latency и retransmits
- RPC — RPC абстрагирует сетевые вызовы, но не проблемы
Вопросы для размышления
- Какие операции в твоём приложении идемпотентны, а какие нет?
- Как бы ты реализовал idempotency key для платёжного API?
- Какой timeout выбрать: слишком короткий → false failures, слишком длинный → медленный UX?