stanislav_dubich@dev:~$ cat url-shortener/README.md
Рефакторинг NodeJS → Java. Разделение путей чтения и записи. Редирект < 20ms, аналитика без ожидания.
Сервис сокращения ссылок с детальной аналитикой переходов. Исходная система на NodeJS + MongoDB не справлялась: медленная аналитика, негибкие лимиты, сложности с масштабированием.
Редирект должен быть мгновенным, но при этом нужно записать ~20 параметров аналитики. Синхронная запись в БД убивает время отклика.
Решение: разделение путей чтения и записи. Редирект из in-memory кэша за < 20ms. Событие аналитики уходит в RabbitMQ без ожидания ответа — пользователь не ждёт записи.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Nginx │────▶│ link-server │────▶│ Memcached │
│ │ │ (редиректы) │ │ (3h TTL) │
└─────────────┘ └──────┬──────┘ └─────────────┘
│ async
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ RabbitMQ │ │ Redis │ │ backend │
│ (hits) │ │(sessions)│ │ (API) │
└────┬─────┘ └──────────┘ └──────────┘
│ Table Engine
┌────▼─────┐
│ClickHouse│
│(analytics)│
└──────────┘
Зачем два кэша: разные типы данных — разные требования.
Проблема: MongoDB не справлялась с аналитическими запросами по миллионам записей.
Решение: RabbitMQ Table Engine для потоковой вставки без промежуточных преобразований. Данные доступны для отчётов с задержкой < 2 сек. ReplacingMergeTree для дедупликации повторных событий.
25+ измерений на каждый переход. Партиционирование по месяцам. Мгновенные срезы по любой комбинации.
Анализ трафика на лету: GeoIP + разбор UserAgent. Блокировка бот-сетей до попадания в аналитику. Стоп-лист с комплексной логикой: IP-диапазоны (CIDR), регулярные выражения по URL, комбинации AND/OR.
Резолвер ссылок (редиректы) и приём аналитики имеют разные требования к масштабированию: ограничение по вводу-выводу vs ограничение по процессору. Независимое масштабирование каждого слоя.
Полный рефакторинг: от legacy NodeJS/MongoDB к микросервисной Java-системе. Архитектура, выбор стека, реализация ключевых сервисов (резолвер ссылок, API Gateway) и вспомогательных воркеров.