Резюме
Миграция логистической платформы регионального транспортного оператора с монолитной PHP-архитектуры на событийно-ориентированную систему на базе стека Go/Kafka/MQTT.
Ключевые бизнес-результаты:
- Пропускная способность: рост с 200 до 10 000+ RPS — запас для масштабирования парка
- Операционные расходы: снижение затрат на мобильный трафик в 5 раз
- Надёжность: переход от SLA 98% к 99.5%
- Защита инвестиций: существующая учётная система (1С) сохранена, нагрузка на неё снижена
Контекст: Простой системы мониторинга транспорта напрямую влияет на операционную эффективность. Событийная архитектура исключает каскадные отказы, характерные для монолитных систем.
1. Проблематика: Анализ рисков Legacy-архитектуры
1.1 Исходное состояние системы
Заказчик эксплуатировал монолит на стеке LAMP (PHP 7.4 / MySQL 5.7). GPS-трекеры отправляли координаты прямыми HTTP-запросами в REST API, который синхронно записывал данные в основную БД.
1.2 Идентифицированные технические риски
Таблица 1. Матрица рисков Legacy-архитектуры
| Категория риска | Проявление | Бизнес-последствия |
|---|---|---|
| Блокировки БД | Lock Wait Timeout при конкуренции запросов | Задержки в отображении на карте |
| Потеря данных | Утрата GPS-точек при разрыве соединения | Неполный трек маршрута |
| Thundering Herd | Переподключение устройств после сбоя сети | Перегрузка системы |
| Vertical Scaling | PHP-FPM: 20-30 МБ RAM на запрос | Рост затрат на инфраструктуру |
1.3 Количественная оценка нагрузки
Расчёт требуемой пропускной способности:
Частота опроса: 1 Гц (GPS + базовая телеметрия)
Текущий парк: N транспортных средств
Целевой рост: 3× (масштабирование парка)
Текущая нагрузка: ~3 000 событий/сек
Целевая нагрузка: ~10 000 событий/сек (с запасом)Вывод: Синхронная модель исходного монолита (предел ~200 RPS) исчерпала лимит масштабирования. Требуется архитектурная трансформация.
2. Архитектурные решения
2.1 Принципы проектирования
Мы применили разделение потоков данных на Hot Path (телеметрия реального времени) и Cold Path (отчётность, синхронизация с учётной системой), реализовав паттерн Event-Driven Architecture.
Рис. 1. Высокоуровневая архитектура системы. Стрелки показывают направление потока данных.
2.2 Обоснование технологического стека
2.2.1 Выбор протокола: MQTT vs HTTP/REST
Таблица 2. Сравнительный анализ протоколов
| Компонент | HTTP/REST | MQTT v5 | Экономия |
|---|---|---|---|
| Минимальный заголовок | 200-400 байт | 2 байта | 100-200× |
| TLS Handshake | На каждый запрос | Однократно | ~300 мс/запрос |
| Payload encoding | JSON (текст) | Binary (Protobuf) | 3-5× |
| QoS механизм | Уровень приложения | Встроенный | — |
Выбор протокола
MQTT v5
Встроенный QoS, Keep-Alive соединения, минимальные накладные расходы (2 байта заголовок).
WebSocket
Отсутствие встроенного QoS — требуется реализация на уровне приложения.
2.2.2 Выбор языка: Go vs Альтернативы
Таблица 3. Сравнение runtime-характеристик
| Параметр | PHP-FPM | Node.js | Go |
|---|---|---|---|
| RAM на соединение | 20-30 МБ | 10-50 КБ | 2-8 КБ |
| GC Pause (p99) | N/A | 5-20 мс | < 1 мс |
| Макс. соединений/нода | ~1 000 | ~50 000 | ~100 000+ |
Выбор языка
Go (Golang)
Goroutines с минимальным потреблением памяти (2-8 КБ на соединение), GC pause менее 1 мс.
Node.js
Выше потребление памяти, event loop не оптимален для CPU-bound задач.
2.2.3 Выбор брокера: Kafka vs Альтернативы
Таблица 4. Сравнение брокеров сообщений
| Критерий | RabbitMQ | Redis Streams | Apache Kafka |
|---|---|---|---|
| Пропускная способность | ~50k msg/s | ~100k msg/s | ~500k msg/s |
| Персистентность | Опционально | Ограничено | Disk-based |
| Replay | Нет | Ограничено | Полный |
Выбор брокера сообщений
Apache Kafka
Возможность повтора событий — при сбое можно «перепроиграть» поток телеметрии. Kafka хранит лог с Retention 7 дней.
RabbitMQ
Удаляет сообщение после ACK — replay невозможен.
3. Механики надёжности
3.1 Transactional Outbox Pattern
Проблема Dual Write: При обновлении статуса заказа сервис должен (1) записать в БД и (2) отправить событие в Kafka. Если БД обновится, а Kafka-publish упадёт — системы рассинхронизируются.
Рис. 2. Паттерн Transactional Outbox с CDC. Debezium читает WAL таблицы outbox_events и гарантирует доставку событий в Kafka.
3.2 Anti-Corruption Layer (ACL)
Проблема Legacy Integration: Прямое подключение новых сервисов к Legacy БД приводит к "протеканию" технического долга.
Рис. 3. Антикоррупционный слой для защиты учётной системы. Circuit Breaker предотвращает каскадный отказ при деградации 1С.
Ключевые механизмы ACL:
- Batching: Группировка событий снижает нагрузку на учётную систему
- Rate Limiting: Контролируемая скорость записи
- Circuit Breaker: При проблемах с 1С — остановка записи, накопление в Kafka
3.3 Store-and-Forward на устройствах
Проблема: Транспорт может находиться в зоне без покрытия. Без локальной буферизации данные теряются.
Решение: Телематические устройства реализуют паттерн Store-and-Forward:
- Локальный буфер — встроенная память на устройстве
- Очередь с приоритетом — при восстановлении связи сначала отправляются критические события (тревоги)
- Дедупликация на сервере — каждое событие содержит уникальный ID
3.4 Идемпотентность обработки
При использовании MQTT QoS 1 и Kafka возможны дубликаты сообщений. Все консьюмеры реализуют идемпотентную обработку через Redis SetNX с TTL.
4. Результаты и метрики
4.1 Сравнительный анализ производительности
Таблица 5. Ключевые метрики: Legacy vs EDA
| Метрика | Legacy Monolith | EDA (Go/Kafka/MQTT) | Улучшение |
|---|---|---|---|
| Throughput | 200 RPS | 10 000+ RPS | 50× |
| Latency (p50) | 2-5 сек | 100-200 мс | 20× |
| Потеря данных | 2-5% при сбоях | Guaranteed Delivery | — |
| 1С CPU Load | 90%+ | 15-20% | 5× |
| SLA | 98% | 99.5% | — |
| Сетевой трафик | Baseline | -80% | 5× |
4.2 Бизнес-результаты
- Масштабирование: система готова к росту парка в 3 раза без изменения архитектуры
- Экономия трафика: снижение затрат на мобильную связь
- Надёжность: сокращение времени простоя
5. Стратегия миграции: Strangler Fig
Миграция выполнялась поэтапно без остановки операций:
Фаза 1 — Shadow Mode (3 недели):
- Развёртывание параллельного стека Go/MQTT/Kafka
- Dual-write: устройства отправляют данные в обе системы
- Валидация данных
Фаза 2 — Read Path Migration (4 недели):
- Dashboards переключены на чтение из Kafka/ClickHouse
- Legacy остаётся System of Record
Фаза 3 — Write Path Migration (4 недели):
- Постепенное переключение устройств на MQTT
- ACL синхронизирует данные в Legacy
Фаза 4 — Завершение (2 недели):
- Отключение HTTP-ingestion в PHP
6. Заключение и рекомендации
Переход на событийно-ориентированную архитектуру с использованием Go/Kafka/MQTT — обоснованный выбор для логистических платформ с требованиями к масштабируемости.
Ключевые выводы:
- MQTT обеспечивает значительное снижение трафика — критично для мобильных сетей
- Kafka предоставляет необходимый запас производительности и гарантии доставки
- Go оптимален для высококонкурентных сценариев IoT
- Transactional Outbox и ACL — обязательные паттерны для безопасной интеграции с Legacy
Рекомендация: Данная архитектура применима к проектам модернизации систем мониторинга транспорта с требованиями к обработке телеметрии и интеграции с существующими учётными системами.