docs: IFT loadtest ceiling ladder ×1→×2×3 and Traefik loadtest overlay.

Refs EventHub/EventHubBack#30

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-16 19:23:03 +03:00
parent 17a97f053f
commit 0585274b8e
+38 -9
View File
@@ -236,25 +236,51 @@ IFT и stage крутят **одну и ту же** сборку `sha-*`. Produc
| Метрика | Значение | | Метрика | Значение |
|---------|----------| |---------|----------|
| Рабочий потолок hot-path | ~**10 VU/s** (interarrival ≥ 0.1 s, thinktime ≥ 1 s) | | Рабочий потолок hot-path (до пересчёта) | ~**10 VU/s** (interarrival ≥ 0.1 s, thinktime ≥ 1 s), прогон ×3 + WAF |
| Green hold | фазы 0.2 / 0.1 s | | Green hold | фазы 0.2 / 0.1 s |
| OVER (connect) | ~20 VU/s (interarrival 0.05) на ×1/×2 | | OVER (connect) | ~20 VU/s (interarrival 0.05) на ×1/×2 (исторически) |
| ×3 | connect держится; упор в rate limit / Mnesia / archive (см. Back#32#34) | | Пересчёт | после fix Mnesia dump_log + Traefik loadtest без WAF: лестница **×1 → ×2 → ×3** |
Подробности: `EventHubBack/test/tsung/README.md`, закрытая задача `EventHubBack#30`. Подробности: `EventHubBack/test/tsung/README.md`, задача `EventHubBack#30`.
### Правила (обязательно) ### Правила (обязательно)
- **Default stress-профиль:** `eventhub_ift_stress_hold.xml` / `stress-hold`. - **Default stress-профиль:** `eventhub_ift_stress_hold.xml` / `stress-hold`.
- `maxusers`**300**; `thinktime`**1** s; плановый interarrival ≥ **0.1** s. - `maxusers`**300** (для `stress-hold` default **100**); `thinktime`**1** s; плановый interarrival ≥ **0.1** s.
- Uncapped / `stress-bump` / `maxusers≫300` на IFT **запрещены** без явного согласования (`CONFIRM_DANGEROUS=1` в оркестраторе). - Uncapped / `stress-bump` / `maxusers≫300` на IFT **запрещены** без явного согласования (`CONFIRM_DANGEROUS=1` в оркестраторе).
- Prepare/restore: `EventHubDevOps/scripts/ift-loadtest-*.sh`; при hang WSL SSH — Windows `restore-ift.ps1` / `wsl --shutdown`. - Prepare/restore: `EventHubDevOps/scripts/ift-loadtest-*.sh`; при hang WSL SSH — Windows `restore-ift.ps1` / `wsl --shutdown`.
- Exchange-share: `collect-ift-loadtest-logs*.ps1`, `restart-wsl-and-collect-logs.ps1`. - **Потолок vs репликация:** сначала `EVENTHUB_REPLICAS=1`, затем 2, 3 — отдельные прогоны с gate; не смешивать ступени.
- Prepare по умолчанию подменяет Traefik на `dynamic_conf.loadtest.yml` (**без WAF**); `LOADTEST_TRAEFIK=0` — штатный conf с Coraza.
### После каждого stress-прогона (обязательно)
Прогон **не считается завершённым**, пока не сделаны сбор, разбор и **очистка дампов на IFT**. Restore без архива — только если стенд уже мёртв и сбор невозможен; тогда collect сразу после `wsl --shutdown`.
1. **Tsung summary (2A):** `python3 test/tsung/summarize-tsung-stress.py ~/.tsung/log/<stamp>/tsung.log``verdict`, error_rate, mean, коды HTTP, transport errors.
2. **Сбор логов стенда** на exchange-share (`\\…\eventhub-cursor\` / `C:\eventhub-cursor-exchange\ift-to-dev\loadtest-<stamp>\`):
- SSH жив: `collect-ift-loadtest-logs.ps1` (после download сам чистит remote dump этого stamp)
- SSH banner hang: `restart-wsl-and-collect-logs.ps1` **или** вручную `wsl --shutdown` на HOME-PC → затем `collect-ift-loadtest-logs.ps1`
- На консоли IFT без SSH: `collect-ift-loadtest-logs-on-ift.sh` (после copy на шару чистит локальные дампы)
3. **Анализ (минимум):**
- сравнить с предыдущим прогоном того же профиля/replicas;
- в архиве: `eventhub-service.log` / `traefik-service.log` — 429, Mnesia `dump_log`, archive/peer, OOM, crash;
- `ift-docker-stats-*.log` / `docker-stats.txt` — CPU/MEM пики;
- **метрики EventHub (обязательно смотреть):**
- scrape `GET https://api.ift.eventhub.local/metrics` (Prometheus text, без auth; eventhub остаётся up в prepare) — до/во время/после; оркестратор пишет сэмплы в `~/.tsung/ift-eh-metrics-*.log`;
- история узлов: `GET /v1/admin/nodes/metrics?from=&to=` (admin JWT) — переживает restart, если volume Mnesia цел;
- стек Grafana/Prometheus (compose) при `KEEP_OBSERVABILITY=1` — опционально; если prepare гасит их, mid-run там пусто;
- зафиксировать: образ `sha-*`, replicas, verdict, узкое место.
4. **Очистка дампов на IFT** (если collect не очистил / остались старые):
`cleanup-ift-loadtest-dumps.ps1` / `EventHubDevOps/scripts/cleanup-ift-loadtest-dumps.sh`
Удаляет `~/loadtest-logs-*`, `/tmp/ift-loadtest-logs-*.tgz`, `/tmp/ift-collect-*.sh`. **Копии на шаре и Tsung на дев не трогает.**
5. **Restore** полного стека (`ift-loadtest-prepare` уже гасит observability; restore поднимает) + smoke health.
6. **Отчёт:** комментарий в issue (`EventHubBack#30`) и/или строка в `EventHubBack/test/tsung/README.md`.
Prepare: по умолчанию compose prometheus/grafana выключены. Для скрейпа **приложения** это не нужно — `/metrics` на eventhub доступен через Traefik всегда, пока up нода. `KEEP_OBSERVABILITY=1` — только если нужен отдельный Prometheus/Grafana стек.
### Критерий верхней границы (2A) ### Критерий верхней границы (2A)
error rate > 1% **или** mean request > 500 ms (hold ≥2 мин в фазе) → `BOUNDARY_HIT`. error rate > 1% **или** mean request > 500 ms (hold ≥2 мин в фазе) → `BOUNDARY_HIT`.
Разбор: `python3 test/tsung/summarize-tsung-stress.py`.
Сравнение hold на bare Linux (без WSL2) — отложено: `EventHubDevOps#4` (Future). Сравнение hold на bare Linux (без WSL2) — отложено: `EventHubDevOps#4` (Future).
@@ -285,7 +311,7 @@ error rate > 1% **или** mean request > 500 ms (hold ≥2 мин в фазе)
- Новая задача — **отдельный чат** с брифом по §5. - Новая задача — **отдельный чат** с брифом по §5.
- **Версии/деплой:** product = `VERSION` (`MAJOR.MINOR`); IFT+stage = `sha-*` (+ floating `:ift`/`:stage`); без ручных stage-тегов и без patch++ на каждый push (см. §6). - **Версии/деплой:** product = `VERSION` (`MAJOR.MINOR`); IFT+stage = `sha-*` (+ floating `:ift`/`:stage`); без ручных stage-тегов и без patch++ на каждый push (см. §6).
- **FrontAdmin E2E:** mock-suite обязателен в CI; IFT smoke — после Deploy IFT (`e2e-ift.yml`, учётки из стендового `.env`). - **FrontAdmin E2E:** mock-suite обязателен в CI; IFT smoke — после Deploy IFT (`e2e-ift.yml`, учётки из стендового `.env`).
- **IFT loadtest:** hold-профиль default; потолок ~10 VU/s; uncapped stress запрещён; recover через Windows SSH / `wsl --shutdown` (см. §7). - **IFT loadtest:** hold-профиль default; потолок пересчитывать лестницей ×1→×2→×3; Traefik loadtest без WAF; uncapped stress запрещён; после stress — collect+анализ (+мониторинг)+**cleanup дампов на IFT**+отчёт+restore (см. §7).
--- ---
@@ -293,6 +319,9 @@ error rate > 1% **или** mean request > 500 ms (hold ≥2 мин в фазе)
| Дата | Изменение | | Дата | Изменение |
|------|-----------| |------|-----------|
| 2026-07-15 | §7: анализ через EventHub `/metrics` + admin `nodes/metrics`; compose Prom опционален |
| 2026-07-15 | §7: cleanup дампов на IFT + мониторинг в анализе; KEEP_OBSERVABILITY |
| 2026-07-15 | §7: сбор и анализ логов — обязательный gate после stress |
| 2026-07-15 | §7: capacity baseline IFT + правила Tsung stress (после EventHubBack#30) | | 2026-07-15 | §7: capacity baseline IFT + правила Tsung stress (после EventHubBack#30) |
| 2026-07-15 | §2.1: пропуск CI — `[skip ci]` / `SKIP_CI=1` в git-commit.sh | | 2026-07-15 | §2.1: пропуск CI — `[skip ci]` / `SKIP_CI=1` в git-commit.sh |
| 2026-07-14 | §6 + gate: Playwright E2E (mock CI + IFT smoke secrets) | | 2026-07-14 | §6 + gate: Playwright E2E (mock CI + IFT smoke secrets) |