Перейти к содержанию

План масштабирования dix.su

Составлен 2026-07-09 на основе анализа текущей архитектуры (см. CAPACITY.md). Реализация каждого следующего тира — по достижении порогов нагрузки предыдущего.


Архитектурный сплит: два типа нагрузки

У платформы два принципиально разных типа нагрузки с разной стратегией масштабирования:

WebSocket-туннели (dixu_proxy) — stateful, long-lived соединения. Каждый device_client держит постоянное WSS-соединение. DeviceRegistry — in-memory ETS на конкретной ноде. При горизонтальном масштабировании нужна межнодовая маршрутизация (Phoenix.Tracker + libcluster), иначе запрос от браузера на ноде B не найдёт устройство на ноде A. Это нетривиальное изменение кода — выполняется на Tier 3.

Веб-трафик (modulauth) — stateless, сессии в Redis. Масштабируется горизонтально тривиально: nginx балансирует на N инстансов, Redis общий.

Вывод: до Tier 3 — вертикальный апгрейд (проще, дешевле, ноль кода). С Tier 3 — горизонталь, но с разным подходом для каждого компонента.


Линейка тиров

Tier 0 — Текущее состояние

Параметр Значение
Сервер 1 vCPU AMD, 1.9 GB RAM, 30 GB SSD, Debian 12
Потолок устройств ~300 device_client одновременно
Потолок пользователей ~200 браузерных сессий одновременно
Активных relay ~50–150 HTTP-запросов
TCP-соединений ~500–1000
Стоимость ~$10–15/мес

Узкие места: 1 CPU (1 BEAM-планировщик), RAM 1.9 GB, nginx 1 worker.

Порог перехода на Tier 1: load average стабильно > 0.7 или свободная RAM < 300 MB.


Tier 1 — Вертикальный апгрейд VPS (×10)

Параметр Значение
Сервер 4 vCPU, 8 GB RAM — апгрейд того же VPS
Потолок устройств ~3 000 device_client одновременно
Потолок пользователей ~2 000 браузерных сессий одновременно
Стоимость ~$40–60/мес

Изменения в коде: ноль. BEAM автоматически задействует все 4 ядра (schedulers_online = 4 — в 4× больше пропускная способность relay). Spring WebFlux тоже масштабируется на все ядра.

Изменения в конфигурации:

# docker-compose.yml → postgres
command: postgres -c max_connections=300

# .env
DB_POOL_SIZE=20
JAVA_OPTS=-XX:+UseZGC -Xms512m -Xmx2g

# nginx dixu.conf.template
worker_connections 4096;

Добавить PgBouncer как промежуточный connection pooler перед Postgres.

Порог перехода на Tier 2: load average стабильно > 3.0 или RAM < 1 GB свободно.


Tier 2 — Выделенный сервер (×10)

Параметр Значение
Сервер 16–32 vCPU, 64 GB RAM — выделенный сервер или облачный инстанс
Postgres Отдельный сервер + read replica для аналитических запросов
Redis Redis Sentinel (HA, 3 ноды)
Потолок устройств ~30 000 device_client одновременно
Потолок пользователей ~20 000 браузерных сессий одновременно
Стоимость ~$200–500/мес

Изменения в коде: ноль.

Изменения в конфигурации: - nginx: worker_processes 16; worker_connections 8192; - Postgres вынесен на отдельный хост, max_connections=500 - Read replica для аналитики (AnalyticsController → replica endpoint) - Redis Sentinel для HA сессий

Партиционирование таблиц аналитики (tunnel_path_visits_daily, tunnel_geo_visits_daily, tunnel_traffic_daily) по дате — к этому моменту таблицы могут вырасти до миллионов строк.

Порог перехода на Tier 3: потребность в >30k одновременных устройств или нужна отказоустойчивость (single point of failure неприемлем).


Tier 3 — Горизонтальный кластер (×10)

Параметр Значение
Конфигурация 3–5 нод dixu_proxy + 3 modulauth + Postgres primary/replica + Redis Cluster + LB
Потолок устройств ~300 000 device_client одновременно
Потолок пользователей ~200 000 браузерных сессий одновременно
Стоимость ~$2 000–5 000/мес

Главное изменение кода — distributed DeviceRegistry:

# mix.exs — добавить libcluster
{:libcluster, "~> 3.3"},
{:phoenix_pubsub, "~> 2.1"}  # уже есть

# lib/dixu_proxy/application.ex — кластеризация
{Cluster.Supervisor, [topology, [name: DixuProxy.ClusterSupervisor]]},
{Phoenix.Tracker, [name: DixuProxy.Tracker, pubsub_server: DixuProxy.PubSub, ...]},

# lib/dixu_proxy_web/channels/proxy_channel.ex
# вместо локального Registry.lookup — Phoenix.Tracker.list

Запрос на ноде B маршрутизируется на ноду A, где реально подключён device_client. Без этого изменения горизонталь для туннелей невозможна.

modulauth — тривиально: 3 инстанса за nginx upstream, Redis Cluster для сессий.

Порог перехода на Tier 4: потребность в мультирегиональности или >300k устройств.


Tier 4 — Облако / Kubernetes (×10)

Параметр Значение
Конфигурация K8s / ECS, 10–30 dixu_proxy pods, 10 modulauth, RDS + read replicas, CloudFront/Cloudflare CDN, multi-AZ
Потолок устройств ~3 млн device_client одновременно
Потолок пользователей ~2 млн браузерных сессий одновременно
Стоимость ~$15 000–50 000/мес

Изменения в коде: - Kubernetes-операторы, HPA (Horizontal Pod Autoscaler) по числу WS-соединений - PostgreSQL партиционирование (Citus или per-table range partitioning) - CDN для всей статики modulauth (CSS/JS/изображения) - Event streaming (Kafka/Kinesis) для аналитики — замена прямых INSERT в dixu_proxy

Порог перехода на Tier 5: международная экспансия с требованиями data residency (GDPR EU, РФ 152-ФЗ) или >3 млн устройств.


Tier 5 — Гиперскейл (VK и выше) (×10+)

Параметр Значение
Конфигурация Multi-region (RU + EU + US + Asia), global anycast LB, database sharding, Erlang geo-clusters
Потолок устройств Десятки миллионов
Потолок пользователей 50–100 млн DAU
Стоимость $200 000+/мес

Ключевые изменения: - Региональные BEAM-кластеры с репликацией метаданных между регионами - Database sharding (Citus PostgreSQL или per-region шарды с global routing) - GDPR-compliant data residency: EU-пользователи → EU-кластер, данные не уходят за регион - Выделенные инженерные команды: SRE, platform, data

Примечание: Erlang/BEAM — это то, на чём построен WhatsApp (2 млрд пользователей, ~50 инженеров). Архитектура dixsu изначально выбрана правильно — технических барьеров для этого масштаба нет. Барьер на Tier 5 — продуктовый и операционный, не технический.


Сводная таблица

Tier Устройств Пользователей Код Стоимость
0 (сейчас) 300 200 ~$15/мес
1 3 000 2 000 Ноль ~$50/мес
2 30 000 20 000 Ноль ~$300/мес
3 300 000 200 000 libcluster + Tracker ~$3 000/мес
4 3 000 000 2 000 000 K8s, CDN, event streaming ~$30 000/мес
5 30 000 000+ 50–100 млн DAU Multi-region, sharding $200 000+/мес

Правило перехода

Переходить на следующий тир по факту достижения порога, а не заранее. Каждый преждевременный апгрейд — это переплата и операционная сложность без отдачи. Erlang/BEAM хорошо держит нагрузку до последнего — пороги видны по load average и свободной RAM, мониторить через docker stats или Prometheus.

Текущий сигнал для старта Tier 1: load average > 0.7 при нормальной работе сервиса.