test(loadtests): 10 load scenarios + verifier; docs: Sonnet review findings
This commit is contained in:
@@ -1068,3 +1068,52 @@ EMQX 4 CPU/2Gi, iot-service 1 CPU/1Gi.
|
||||
|
||||
### 30.3 Запрос Sonnet (код-ревью + план тестов)
|
||||
Статус: ЗАПРОШЕН — результат в секции 31.
|
||||
|
||||
---
|
||||
|
||||
## 31. Sonnet-ревью + набор нагрузочных тестов (16:10 GMT+03)
|
||||
|
||||
### 31.1 Ревью Sonnet — ключевые находки (полный отчёт сохранён в чате)
|
||||
20 находок. ВАЖНЕЙШИЕ (проверено по коду):
|
||||
1. **CRITICAL** `internal/service/bridge/handler.go:50` — `SendMessage` в SQS
|
||||
синхронный внутри MQTT-колбэка paho (сериализованный диспатч). При
|
||||
недоступности SQS (таймаут ~30с) блокируется приём ВСЕХ MQTT-сообщений
|
||||
→ потери. ФИКС: канал + worker-пул, дроп при переполнении. ПОДТВЕРЖДЕНО.
|
||||
2. **HIGH** consumer: VisibilityTimeout=30с vs EnsureTenantDB (CREATE DATABASE
|
||||
5-10с + user + grant + table) → дубли при медленной обработке. ФИКС:
|
||||
VisibilityTimeout 120-180с или раздельная обработка.
|
||||
3. **HIGH** consumer: нет backoff при падении PG → лавина ретраев после
|
||||
восстановления. ФИКС: exponential backoff + jitter, DLQ.
|
||||
4. **MEDIUM** main.go: shutdown — HTTP гаснет раньше bridge/consumer →
|
||||
liveness-килл. ФИКС: сначала bridge/consumer, потом HTTP.
|
||||
5. **MEDIUM** iotpg.InsertTelemetry без батчинга (1000 msg/s = 1000 INSERT).
|
||||
ФИКС: буфер + batch INSERT.
|
||||
Прочие: гонка getTenantDB (singleflight), лимит tenant-БД (whitelist),
|
||||
defer в цикле AdminStats, MaxOpenConns=5 (devices/admin), List без пагинации,
|
||||
JWT без подписи (архитектурно), валидация MQTT_BROKER_URL, топик в bridge
|
||||
(пустой ns), CREATE USER через Sprintf (%I/%L), логирование пустых SQS-body,
|
||||
молчаливый дроп битого JSON, subscribe-таймаут не фатален.
|
||||
СТАТУС: НИЧЕГО НЕ ИСПРАВЛЕНО — ждём команду «делай» по фиксам.
|
||||
|
||||
### 31.2 Набор нагрузочных тестов — создан `loadtests/`
|
||||
Python-пакет (paho-mqtt + stdlib), запуск: `python3 -m loadtests.run <сценарий>`.
|
||||
10 сценариев: baseline, burst, large-payload, reconnect-storm, multitenant,
|
||||
acl-violation, auth-neg, api-crud, telemetry-query, soak.
|
||||
Механика: тест сам создаёт устройства (namespace lt_*) через API, публикует
|
||||
payload {run_id, seq, sent_at, pad}, верификатор сверяет доставку через API:
|
||||
delivered/lost/duplicates/latency (p50/p95/p99, ts(PG)-sent_at, NTP).
|
||||
Документация и критерии успеха — loadtests/README.md; ручные SQS/PG-outage
|
||||
тесты (через kubectl) описаны там же.
|
||||
Грабли: POST /devices НЕ возвращает пароль (только GET по имени — учтено);
|
||||
paho connect() rc=0 даже при CONNACK≠0 (on_connect обязателен); ts парсится
|
||||
через datetime.fromisoformat (таймзона!); API отдаёт ≤1000 строк.
|
||||
|
||||
### 31.3 Смоук-прогон (прод, минимальная нагрузка)
|
||||
- auth-neg: wrong_password rc=4, unknown_user rc=5 — PASS.
|
||||
- baseline (2 устройства, 0.5 msg/s, 10с): sent 10, delivered 10/10,
|
||||
lost 0, duplicates 0, latency p50≈208мс, первое сообщение ≈1.25с
|
||||
(consumer long-poll). PASS.
|
||||
|
||||
### 31.4 Дальше
|
||||
- Ждём «делай» по фиксам из 31.1 (минимум №1 и №2 перед большими нагрузками).
|
||||
- Прогон полных сценариев — по команде.
|
||||
|
||||
Reference in New Issue
Block a user