mirror of
https://github.com/Av0idD4rk/packmate.git
synced 2026-10-23 15:31:00 +00:00
127 lines
12 KiB
Markdown
127 lines
12 KiB
Markdown
# Очистка старых потоков
|
||
|
||
В режиме `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 секунд:
|
||
|
||
```dotenv
|
||
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 не используется.
|
||
|
||
```bash
|
||
./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.
|
||
|
||
```bash
|
||
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
|
||
контейнеров.
|
||
|
||
Для длительного прогона на миллион соединений:
|
||
|
||
```bash
|
||
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.
|