Производительность и масштабирование: как SEG-T держит нагрузку
Привет! Сегодня поговорим о теме, которую часто обходят стороной в продуктовых блогах, но которая определяет, выдержит ли система реальную нагрузку — производительность и масштабирование SEG-T.
Статья для тех, кто хочет понять, как устроена система под капотом — от пулов воркеров до кэширования и лимитов. Без маркетинга, только архитектура.
Почему это важно
- Email не ждёт — задержка в секунды допустима, в минуты — уже инцидент
- Нагрузка неравномерна — утренний пик, рассылки, спам-волны создают кратковременные всплески в 5–10x
- Каждое письмо — pipeline — антиспам, антивирус, DNS-резолвинг, правила, AI-анализ, доставка
- Горизонтальный рост — архитектура должна масштабироваться добавлением инстансов, а не переписыванием
Архитектура сервисов
SEG-T разделён на четыре независимых процесса. Каждый масштабируется отдельно, без общего состояния в памяти:
API-сервер
HTTP-сервер для дашборда и внешних интеграций. Stateless — любой запрос может обработать любой инстанс.
Consumer
Обработка email-потока из очереди сообщений. Основной вычислительный процесс — анализ, фильтрация, доставка.
Cron
Фоновые задачи — отчёты, очистка, health-checks, статистика. Лёгкий процесс с минимальным потреблением ресурсов.
Reports
Генерация PDF-отчётов — ресурсоёмкая операция, вынесена в отдельный процесс. Масштабируется независимо.
Все сервисы stateless. Состояние хранится в PostgreSQL, кэш — в Redis, поток сообщений — в Kafka. Инстанс можно убить и поднять без потери данных.
Пулы воркеров
Ядро производительности — конкурентные пулы воркеров на базе семафоров. Каждый модуль получает свой пул с настраиваемым размером:
Основной pipeline: антиспам, DNS, AI-анализ. Критический путь
Доставка, карантин, блокировка. Финальный этап обработки
Управление доменами, пользователями, настройками
Применение пользовательских правил фильтрации
Отправка HTTP-уведомлений во внешние системы
Email и Telegram-уведомления администраторам
Генерация PDF — тяжёлые операции с ограниченным параллелизмом
Размер каждого пула настраивается под нагрузку. На минимальной облачной конфигурации (4 vCPU / 8 GB RAM) система показывает многократное ускорение по сравнению с последовательной обработкой.
Многослойное кэширование
Каждый запрос к базе данных, который повторяется чаще раза в минуту, проходит через кэш. Стратегия — write-through invalidation: данные кэшируются при чтении, инвалидируются при записи.
Статистика
Сводка, временные ряды, срезы по доменам, угрозам, IP, отправителям
Домены
Конфигурация домена, MX-записи, настройки фильтрации
Ключи (JWKS)
Активные ключи, поиск по идентификатору, публичные ключи
Карантин
Списки, подсчёты, фильтрация по статусу
Инвалидация работает на двух уровнях: HTTP-мидлварь перехватывает мутирующие запросы, а consumer инвалидирует кэш при обработке событий из очереди сообщений.
DNS-кэширование
Каждое входящее письмо требует DNS-резолвинга — SPF, DKIM, DMARC, MX-записи. Без кэша каждый запрос добавляет ощутимую задержку. С кэшем — на порядки быстрее:
×1
без кэша
×100
с DNS-кэшем
TTL кэша настраивается. Кэшируются TXT, A и MX записи отдельно.
Rate limiting
Защита от перегрузки — как внешней (DDoS, сканеры), так и внутренней (баги в интеграциях, зацикленные скрипты). Лимиты распределённые, работают через атомарные операции. Каждый endpoint получает свой лимит в зависимости от критичности.
При превышении клиент получает стандартный ответ с информацией о времени до сброса лимита. Идентификация — по нескольким параметрам одновременно, что затрудняет обход.
Пулы соединений
Открытие соединения с базой — дорогая операция. Пулы держат соединения тёплыми и переиспользуют их:
PostgreSQL
Настраиваемые лимиты min/max соединений, lifetime и idle timeout. Периодический health-check для раннего обнаружения проблем.
Redis
Пул с настраиваемым размером и idle-лимитами. Автоматические ретраи при ошибках, конфигурируемые read/write таймауты.
Нагрузочное тестирование
Система проходит нагрузочные тесты на каждом релизе. Сценарии: smoke, load, stress, spike. Результаты в минимальной конфигурации (4 vCPU / 8 GB RAM):
Stress
Плавный рост нагрузки до сотен виртуальных пользователей. Ошибки менее 0.01%.
Extreme
Нагрузка до тысячи VU. Система сохраняет стабильность, ошибки менее 1%.
Spike
Мгновенный рост нагрузки в 100 раз за секунды. Сервер не падает, восстанавливается после сброса.
Горизонтальное масштабирование
Все сервисы спроектированы для горизонтального масштабирования:
- API-сервер — добавляем инстансы за балансировщиком, без sticky sessions
- Consumer — масштабируется через партиционирование очереди сообщений
- Reports — независимый пул, не влияет на основной поток
- Хранилище — PostgreSQL (ACID), Redis (кэш), Kafka (поток), S3 (объекты) — все shared
Прогноз при масштабировании одного consumer-инстанса:
Устранение сетевых задержек на резолвинг — кратный рост throughput
Группировка операций с БД — снижение числа round-trip
Распределение потока по нескольким consumer-инстансам
Производительность — не фича, а свойство архитектуры. Мы закладываем масштабирование на каждом уровне: от пулов соединений до партиционирования очередей. Следите за дневником — здесь публикуются обновления и технические детали продукта.