Files
IoT/loadtests/README.md
T

5.6 KiB
Raw Blame History

Нагрузочные тесты IoT

Контур: устройство → wss (EMQX) → бридж → SQS iot-telemetry → consumer → PG → API.

Запуск

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.

Примеры:

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.