# SQS-service Progress ## Версия v0.1.x ### v0.1.21 (2026-04-11) — Redis schema v2 + per-message persistence - ✅ Redis schema v2: metadata в HASH `ssq:queues`, сообщения в отдельных HASH `ssq:msg:{queueKey}` - ✅ Per-message persistence: каждая операция (send/receive/delete/visibility) пишет только затронутое сообщение - ✅ Migration v1→v2: автоматическая миграция при старте (59 очередей мигрировано) - ✅ quick_test: 31/31 PASS - ✅ shared_sqs_test: 28/28 PASS - **Docker image:** `naeel/shared-sqs:v0.1.21` ### Производительность v0.1.21 (benchmark) | Размер | shared-sqs | Yandex MQ | Сравнение | |--------|-----------|-----------|-----------| | 1KB | ~800ms | ~700ms | Паритет | | 10KB | ~800ms | ~700ms | Паритет | | 32KB | **805-917ms** | 869-3490ms | **Быстрее** (нет cold start) | | 64KB+ | ❌ 10-52s зависание | ~900ms | Проблема nginx+botocore | ### Проблема 65KB+ payload (расследование 2026-04-11) **Root cause:** botocore (AWS SDK) + urllib3 2.0 + TLS record boundary. - urllib3 2.0 отправляет headers и body двумя отдельными send() вызовами - botocore убирает TCP_NODELAY (алгоритм Nagle включён) - Последняя TLS-запись (~16KB) застревает из-за Nagle + delayed ACK - nginx `client_body_timeout` срабатывает → HTTP 408 **Попытка фикса nginx:** - ConfigMap: `client-body-timeout: "120"`, `client-body-buffer-size: "2m"` — применилось - Аннотация `proxy-request-buffering: "off"` — НЕ подхватилась shturval controller - pip boto3 (Python 3.12): исправлено (84ms → 13ms) ✅ - AWS CLI (Python 3.14.3 bundled): всё ещё зависает (51843ms) ❌ **Финальный вывод (2026-04-12):** - проблема локализована на стороне platform ingress controller штурвала, а не в Go-сервисе shared-sqs; - ingress приложения корректен, но controller выборочно применяет аннотации: `proxy-body-size` и `client-body-buffer-size` доходят до nginx.conf, а `proxy-request-buffering` остаётся `on`; - upstream ingress-nginx эту аннотацию поддерживает, значит это platform-specific limitation/bug; - hard-limit 32KB в код shared-sqs НЕ вводим; - 32KB остаётся практической рекомендацией для AWS CLI / botocore в текущей инфраструктуре. ### v0.1.19 (2026-04-11) ✅ — ПРЕДЫДУЩАЯ DEPLOYED - ✅ Валидация VisibilityTimeout (0–43200) в ReceiveMessage - ✅ Валидация WaitTimeSeconds (0–20) в ReceiveMessage - ✅ Пустой MessageBody → MissingParameter в SendMessage - ✅ quick_test: **31/31** ✅ - ✅ hardcore_test: **114/116** ✅ (2 flaky — 100KB TLS, не баг сервера) - ✅ stress_test: **21/23** ✅ (2 flaky — сеть/nginx, не баг сервера) - **Docker image:** `naeel/shared-sqs:v0.1.19` - **Helm:** `deployments/helm/shared-sqs/` appVersion v0.1.19 ### v0.1.18 (2026-04-11) ✅ - ✅ 4 новые API команды: ChangeMessageVisibilityBatch, TagQueue, UntagQueue, ListQueueTags - ✅ Итого API: **17 команд** (полная Yandex/AWS SQS совместимость) - ✅ security: fix critical/high auth, idor, races and persistence - ✅ security: address medium risks in jwt, redis ordering and body limit - ✅ perf: optimize receive long polling and finalize formatting cleanup ### v0.1.15 (2026-04-10) ✅ - ✅ JWT auth через nubes API (deck-api-test.ngcloud.ru) - ✅ Login page в UI (ввод токена → валидация → auto-provisioning tenant) - ✅ /ui/api/* защищены JWT middleware - ✅ TenantID совместим с sless namespace: sless-{SHA256(sub)[:8]} ### v0.1.14 (2026-04-10) ✅ - ✅ Фикс критического дедлока в `create_queue.go` - ✅ Фикс UI: `m.sent` → `m.sent_at` - ✅ Redis write-through persistence - ✅ TLS Ingress: `qu.kube5s.ru` ### Security & Compatibility Wave (2026-04-10) ✅ - ✅ SigV4 подпись, IDOR fix, map race fix, persistence sync - ✅ shared_sqs_test.sh PASS=28 FAIL=0 ## Стресс-тестирование (2026-04-11) ✅ ### Результаты stress_test.sh v2 (финальный прогон) | # | Секция | Результат | Детали | |---|--------|-----------|--------| | 1 | Подготовка (тенанты, очереди) | ✅ | 3 тенанта, автогенерация AK/SK | | 2 | Конкурентная отправка (10×20) | ✅ | 200/200 доставлено | | 3 | Конкурентное чтение | ✅ | 200 прочитано, 200 удалено, 0 в очереди | | 4 | Multi-tenant изоляция | ✅ | 0 чужих сообщений, 3×30=90 своих | | 5 | Burst (50 одновременно) | ✅ | 50/50 доставлено | | 6 | Kill pod + восстановление | ✅ | Данные из Redis — 100% recovery | | 7 | Redis disconnect | ✅ | HTTP 200 из кеша, graceful degradation | | 8 | Смешанная нагрузка (15s) | ✅* | send+recv+delete+attr, 1 flaky attr | | 9 | Cleanup | ✅ | Тенанты и очереди удалены | **Итого: 21/23 ✅, 2 ❌ (flaky сеть, не баги сервера)** ### Покрытие тестами | Тест | Что проверяет | Результат | |------|---------------|-----------| | quick_test.sh | 17 SQS команд, smoke | 31/31 ✅ | | hardcore_test.sh | Edge cases, лимиты, ошибки | 114/116 ✅ | | stress_test.sh | Конкурентность, resilience, isolation | 21/23 ✅ | | **Всего** | | **166/170 ✅ (97.6%)** | ## Next Steps - [ ] Per-queue locking (заменить глобальный мьютекс на per-queue sync.RWMutex) - [ ] DLQ (Dead Letter Queue) — maxReceiveCount → перемещение в DLQ - [ ] Rate limiting per tenant - [ ] Prometheus метрики (exporter) - [ ] Горизонтальное масштабирование (leader election или Redis-based state) - [ ] Long polling оптимизация (channel-based вместо 100ms polling) - [ ] Go unit tests (`go test ./...`) ### v0.1.15 (2026-04-10) ✅ - ✅ JWT auth через nubes API (deck-api-test.ngcloud.ru) - ✅ Login page в UI (ввод токена → валидация → auto-provisioning tenant) - ✅ Email пользователя в navbar - ✅ /ui/api/* защищены JWT middleware (больше не публичные) - ✅ TenantID совместим с sless namespace: sless-{SHA256(sub)[:8]} - ✅ Сессия в localStorage (token + email) - [ ] Docker build + deploy + E2E test ## Known Limitations 1. **Глобальный мьютекс** — SyncQueues.Lock() на весь сервис. При >50 rps — bottleneck. Стресс-тест подтвердил: работает корректно (нет deadlock/race), но сериализует все операции. 2. **Нет DLQ** — сообщения после maxReceiveCount не перемещаются. Для production — must-have. 3. **Long Polling наивный** — polling каждые 100ms. При 20 клиентах = 200 poll/sec на пустую очередь. 4. **Нет rate limiting** — один тенант может degradировать сервис для остальных. 5. **Single pod** — replicas > 1 не работает из-за глобального мьютекса (два пода = два state). 6. **Нет метрик** — Prometheus exporter отсутствует. 7. **100KB сообщения** — 2/116 flaky в hardcore_test (TLS/nginx buffer, не баг сервера). ## Architecture ``` SQS-service/ ├── app/ │ ├── cmd/main.go — точка входа │ ├── models/model.go — Queue, Message, Tenant структуры │ ├── gosqs/*.go — реализация SQS API операций │ ├── admin/admin.go — Admin API (Create/List/Get Tenant) │ ├── tenant/tenant.go — Multi-tenant изоляция │ ├── auth/auth.go — AWS Signature V4 верификация │ ├── persistence/redis.go — Redis adapter для persistence │ ├── router/router.go — HTTP маршруты │ └── ui/index.html — Web Console ├── deployments/k8s/ — Kubernetes манифесты ├── tests/ — E2E тесты └── doc/ — Документация ``` ## Technology Stack - **Language**: Go 1.22 - **HTTP Server**: Go std net/http - **Auth**: AWS Signature V4 - **Storage**: Redis (write-through) - **Container**: Docker - **Orchestration**: Kubernetes - **DNS**: Ingress с TLS ## Demo Credentials (read-only для тестирования) ``` Access Key: SSAK-demo-shared-sqs Secret Key: demo-secret-key-shared-sqs-ngcloud-2026 Endpoint: https://qu.kube5s.ru ``` ## Deployment ```bash # Kubernetes kubectl apply -k deployments/k8s/ # Docker (local) docker run -p 9090:9090 naeel/shared-sqs:v0.1.14 ``` --- *Last updated: 2026-04-10*