test(loadtests): 10 load scenarios + verifier; docs: Sonnet review findings

This commit is contained in:
“Naeel”
2026-08-16 16:59:29 +04:00
parent a4a11bae54
commit 090cedca67
14 changed files with 1024 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
# Нагрузочные тесты IoT
Контур: устройство → wss (EMQX) → бридж → SQS `iot-telemetry` → consumer → PG → API.
## Запуск
```bash
cd loadtests
python3 -m loadtests.run <scenario> [опции]
# или из корня репо:
python3 -m loadtests.run <scenario> [опции]
```
Требования: Python 3.10+, `paho-mqtt` (`pip install paho-mqtt`).
Конфигурация через env (дефолты — прод):
| Env | Дефолт |
|---|---|
| `IOT_API` | `https://iot.containerk8s.dev.nubes.ru` |
| `IOT_WS` | `wss://exqx.containerk8s.dev.nubes.ru/mqtt` |
| `IOT_NS_PREFIX` | `lt` |
| `IOT_CLEANUP` | `1` (удалять созданные тестом устройства) |
Тест сам регистрирует устройства через API (JWT структурный) в namespace
`lt_<run-id>` и удаляет их после прогона при `IOT_CLEANUP=1`.
## Сценарии
| Сценарий | Что проверяет |
|---|---|
| `baseline` | Равномерная нагрузка: потери/дубли/задержка (p50/p95/p99) доставки в PG. |
| `burst` | Всплеск xN: рост очереди и время восстановления (recovery). |
| `large-payload` | Payload до ~900KB (лимит EMQX 1MB). |
| `reconnect-storm` | Периодические разрывы соединений (эмуляция edge-разрывов ~150с), QoS1. |
| `multitenant` | Много namespace: задержка первого сообщения (EnsureTenantDB). |
| `acl-violation` | Публикация в чужой топик → EMQX должен рвать сессию. |
| `auth-neg` | Неверный пароль → CONNACK 4, неизвестный юзер → CONNACK 5. |
| `api-crud` | Нагрузка на CRUD устройств (POST/GET/DELETE). |
| `telemetry-query` | Нагрузка на чтение телеметрии. |
| `soak` | Длительный прогон с периодическими срезами sent/delivered. |
Примеры:
```bash
python3 -m loadtests.run baseline --devices 50 --rate 2 --duration 120 --qos 0
python3 -m loadtests.run burst --devices 100 --rate 1 --burst-mult 10 --duration 30
python3 -m loadtests.run reconnect-storm --devices 100 --rate 1 --reconnect-every 30 --duration 300
python3 -m loadtests.run multitenant --tenants 20 --devices-per-tenant 3
python3 -m loadtests.run api-crud --threads 10 --iterations 20
python3 -m loadtests.run telemetry-query --threads 10 --iterations 50 --query-limit 100
python3 -m loadtests.run soak --devices 50 --rate 1 --duration 3600 --slice-sec 300
```
## Ограничения
- API отдаёт максимум **1000 строк** телеметрии на запрос → верификатор
считает окно ~900 сообщений на устройство. Сценарии с большим expected
на устройство недосчитают (для точных потерь — дробить на прогоны).
- Задержка = `ts(PG) - sent_at - skew`; skew калибруется первым сообщением
(часы тест-машины и PG могут расходиться).
- Consumer long-poll до ~20с → после публикаций нужна пауза перед сверкой
(встроена в сценарии).
## Критерии успеха (базовые)
- `baseline`: loss_rate = 0, duplicates = 0, p99 < 10с при ≤100 msg/s.
- `burst`: recovery < 120с после конца пика.
- `reconnect-storm`: loss_rate < 0.01 (QoS1), forced_reconnects > 0.
- `acl-violation`: foreign_accepted = 0.
- `auth-neg`: rc = 4 и rc = 5.
- `soak`: delivered растёт монотонно, провалов нет.
## Тесты с отключением сервисов (вручную, нужен kubectl с ВМ)
Снаружи отключить SQS/PG нельзя — их блокируют на кластере:
1. **SQS-outage** (обрыв бриджа): заблокировать egress монолита к shared-sqs
network policy или `kubectl delete endpoints` — 3 минуты, затем восстановить;
метрики: ошибки SendMessage в логах бриджа, время восстановления доставки.
(Известная проблема: SendMessage в handler блокирует MQTT-поток — см. HISTORY
секция 31, Sonnet-ревью, находка №1.)
2. **PG-outage**: `kubectl -n <pg-ns> scale deployment postgresqlk8s --replicas=0`
на 5 минут; метрики: глубина SQS (ApproximateNumberOfMessages), дубли после
восстановления (visibility timeout 30с — см. находку №2 ревью).
Оба теста — ТОЛЬКО на стенде, не на проде.
## Что гонять на проде
Умеренно (безопасно): `baseline` (≤100 msg/s), `auth-neg`, `acl-violation`,
`api-crud`, `telemetry-query`, `multitenant` (≤20 тенантов).
Осторожно (off-peak): `burst` (x10 кратко), `reconnect-storm` (≤100 устройств),
`large-payload` (≤5 устройств).
Не на проде: SQS-outage, PG-outage, `soak` >1ч с высоким rate.