test(loadtests): 10 load scenarios + verifier; docs: Sonnet review findings
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user