12 KiB
Очистка старых потоков
В режиме LIVE Packmate периодически удаляет старые потоки, кроме отмеченных как favorite. Удаление выполняется короткими независимыми транзакциями напрямую в PostgreSQL и не загружает граф Stream -> Packet -> FoundPattern в Hibernate.
По умолчанию очистка включена в Docker Compose и сохраняет последние 15 минут:
| Переменная | Значение | Назначение |
|---|---|---|
PACKMATE_OLD_STREAMS_CLEANUP_ENABLED |
true |
Включает задачу |
PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD |
15 |
Retention для non-favorite потоков в минутах |
PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL_SECONDS |
10 |
Пауза между запусками в секундах |
PACKMATE_OLD_STREAMS_CLEANUP_MAX_RUN_SECONDS |
5 |
После этого cleaner не начинает новые пачки |
PACKMATE_OLD_STREAMS_CLEANUP_COMMIT_GRACE_SECONDS |
120 |
Минимальное время после записи до очистки |
PACKMATE_OLD_STREAMS_CLEANUP_BATCH_SIZE |
500 |
Максимум потоков в транзакции |
PACKMATE_OLD_STREAMS_CLEANUP_MAX_BATCHES_PER_RUN |
20 |
Максимум транзакций за один запуск |
PACKMATE_OLD_STREAMS_CLEANUP_MAX_PACKETS_PER_BATCH |
20000 |
Бюджет пакетов на транзакцию |
PACKMATE_OLD_STREAMS_CLEANUP_MAX_MATCHES_PER_BATCH |
20000 |
Бюджет найденных совпадений на транзакцию |
PACKMATE_OLD_STREAMS_CLEANUP_MAX_BYTES_PER_BATCH |
67108864 |
Бюджет содержимого на транзакцию |
PACKMATE_OLD_STREAMS_CLEANUP_STATEMENT_TIMEOUT_SECONDS |
5 |
Общий deadline одной cleanup-транзакции |
PACKMATE_OLD_STREAMS_CLEANUP_LOCK_TIMEOUT_SECONDS |
1 |
Лимит ожидания блокировки |
PostgreSQL запускается с более частым autovacuum. Параметры заданы также в docker-compose.yml, поэтому применяются к уже существующему volume после перезапуска контейнера БД.
Перед удалением поток помечается как находящийся в очистке и перестаёт попадать в выдачу и lookback. Пакеты удаляются ограниченными кусками. Если приложение или БД перезапустятся посередине, следующий запуск продолжит такой поток. Поэтому один большой TCP stream не блокирует всю очередь очистки.
Retention и частота полностью настраиваются через .env. Например, чтобы хранить час истории и запускать cleaner каждые 30 секунд:
PACKMATE_OLD_STREAMS_CLEANUP_THRESHOLD=60
PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL_SECONDS=30
В старых конфигурациях интервал задавался в минутах через PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL.
Теперь используется PACKMATE_OLD_STREAMS_CLEANUP_INTERVAL_SECONDS; старую переменную нужно заменить.
MAX_RUN_SECONDS ограничивает момент запуска следующей пачки. Внутри пачки оставшееся время SQL
пересчитывается перед каждым запросом, поэтому вся транзакция ограничена STATEMENT_TIMEOUT_SECONDS.
Для соревнований effective cleanup throughput должен быть выше скорости, с которой трафик пересекает retention cutoff. Если Packmate начинает деградировать через 25–30 минут, безопасный исходный retention — 15 минут; favorite потоки не удаляются.
Стресс тест
Тест всегда создаёт одноразовый PostgreSQL через Testcontainers. Рабочая база Packmate не используется.
./gradlew stressTest
Стандартный профиль создаёт 30 000 обычных потоков, oversized поток с ложной метаинформацией и более 900 000 пакетов. Он использует production лимиты запусков и паузы, параллельно запускает два writer и проверяет:
- удаление всех старых non-favorite данных и сохранение favorite/new данных;
- отсутствие потерянных новых записей и orphan rows;
- возобновление oversized потока несколькими ограниченными транзакциями;
- p99 задержки ingest не выше 500 мс;
- длительность одной cleanup пачки не выше 5 секунд;
- скорость очистки не ниже 5 000 пакетов/с;
- запуск autovacuum и снижение dead tuples до 50 000.
Отчёт сохраняется в build/reports/cleanup-stress.json. Размер нагрузки и пороги настраиваются переменными PACKMATE_STRESS_*, перечисленными в OldStreamsCleanerStressTest.
Сетевой end-to-end stress test
OldStreamsCleanerStressTest изолирует производительность PostgreSQL. Отдельный Linux/Docker стенд
проверяет весь production тракт: реальные TCP соединения через Docker veth, захват libpcap,
сборку потоков, очередь обработчика, Hibernate, PostgreSQL, cleaner и REST API.
sh stress/network/run.sh
По умолчанию тест создаёт 250 000 исходных TCP соединений и ещё 50 000 соединений во время очистки. В каждом соединении передаётся восемь пар request/response с payload 1024 байта. Нагрузка распределяется между 16 контейнерами с отдельными source IP, чтобы один диапазон ephemeral ports не ограничивал результат. Это около 4,8 млн прикладных сообщений плюс TCP handshake, ACK и FIN.
Перед очисткой тест полностью выгружает ledger сохранённых потоков и для каждого независимо проверяет
run_id, connection ID, shard, полную длину и MD5 payload в обоих направлениях, а также IP адреса.
Дополнительно 200 потоков проверяются через REST API. После этого тест
искусственно сдвигает timestamp уже захваченных строк за retention cutoff, чтобы проверить production
cleaner без ожидания полного retention period, и одновременно продолжает подавать свежий сетевой трафик.
Тестовый retention по умолчанию равен 1440 минутам, поэтому случайно свежие строки не попадают в cleanup.
Live фаза длится не менее 20 секунд и PASS возможен только при измеренном пересечении commit новых
потоков с удалением baseline.
Тест завершается ошибкой при любой ошибке генератора, потере сохранённого потока, повреждении
проверяемого payload, pcap drop, capture queue более 500 000 пакетов, orphan row, незавершённом cleanup
или REST p99 выше 500 мс. После baseline проверяется ранний gate, поэтому заведомо повреждённый прогон
не маскирует потери длительным ожиданием ingest. Размер capture queue измеряется монотонным high water
mark внутри приложения. При превышении лимита monitor создаёт общий abort marker, и все генераторы
перестают открывать новые соединения. Cleaner должен удалять не менее 500 streams/s; порог настраивается.
PostgreSQL создаётся в отдельном Compose project на
одноразовом Docker volume; до нагрузки проверяется доступное место. Рабочая база Packmate не используется.
JSON отчёты, effective config, overlap timeline и логи сохраняются в отдельном каталоге запуска под
build/reports/network-stress/.
Контрольный запуск 23 октября 2026 года показал предел старого однопоточного capture path: при 250 000
TCP соединений libpcap сообщил 1 967 297 drops, а неограниченная очередь выросла до 4 894 878 задач.
После перехода на 12 flow-sharded workers повторный baseline сохранил 250 000 из 250 000 соединений и
8 013 904 захваченных пакета без kernel, interface или application drops. Полный ledger подтвердил
payload и метаданные всех 250 000 потоков; очередь полностью опустела, её high water составил 61 396
из 500 004 задач. Следующая волна передала ещё 50 000 соединений во время cleanup без ошибок генератора
и packet drops; её high water составил 120 570.
Отдельный завершённый профиль 5 000 + 1 000 прошёл весь ingest/cleanup/ledger цикл, включая измеренное
пересечение cleaner с live traffic, сохранение favorite, REST p99 189,686 мс и отсутствие orphan rows.
Production по умолчанию сохраняет PACKMATE_CAPTURE_WORKERS=1 как безопасный режим совместимости;
число workers нужно выбирать по результатам этого стенда на реальном сервере. Throughput генераторов
измеряется от старта первого до завершения последнего workload-процесса и не включает создание Docker
контейнеров.
Для длительного прогона на миллион соединений:
PACKMATE_NETWORK_STRESS_STREAMS=1000000 \
PACKMATE_NETWORK_STRESS_LIVE_STREAMS=100000 \
PACKMATE_NETWORK_STRESS_SHARDS=16 \
sh stress/network/run.sh
Основные параметры: PACKMATE_NETWORK_STRESS_STREAMS, PACKMATE_NETWORK_STRESS_LIVE_STREAMS,
PACKMATE_NETWORK_STRESS_SHARDS, PACKMATE_NETWORK_STRESS_CONCURRENCY,
PACKMATE_NETWORK_STRESS_FRAMES_PER_STREAM, PACKMATE_NETWORK_STRESS_PAYLOAD_BYTES,
PACKMATE_NETWORK_STRESS_MAX_CAPTURE_QUEUE, PACKMATE_NETWORK_STRESS_MIN_LIVE_DURATION_SECONDS,
PACKMATE_NETWORK_STRESS_MIN_CLEANUP_STREAMS_PER_SECOND и таймауты
PACKMATE_NETWORK_STRESS_*_TIMEOUT_SECONDS. PACKMATE_NETWORK_STRESS_RUN_ID задаёт имя каталога отчёта.
В GitLab CI малый профиль network-smoke обязателен, а дорогой capacity профиль доступен как ручной job
network-stress; отчёты обоих сохраняются как artifacts.