100 lines
5.6 KiB
Markdown
100 lines
5.6 KiB
Markdown
# Нагрузочные тесты 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
|
||
```
|
||
|
||
## Ограничения
|
||
|
||
- **SQS-лимит 256KB** на сообщение (shared-sqs отклоняет: `InvalidParameterValue
|
||
message size exceeds the limit`) → payload устройств ≤ ~250KB с учётом
|
||
envelope. Бридж дропает oversize с логом `payload too large for SQS`.
|
||
EMQX пропускает до 1MB, но узким местом конвейера является SQS.
|
||
- API отдаёт максимум **1000 строк** телеметрии на запрос; шлюз платформы
|
||
рвёт ответы >~15КБ (баг MSS/MTU, тикет Nubes) → верификатор ходит
|
||
страницами по 50 (`offset`). Большие страницы НЕ использовать.
|
||
- Задержка = `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.
|