9.9 KiB
9.9 KiB
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, сообщения в отдельных HASHssq: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 | 880-965ms | 916-996ms | Быстрее |
| 32KB | 883-939ms | 905-948ms | Быстрее |
| 64KB+ | ❌ 10-52s зависание | ~900ms | Проблема nginx+botocore |
- Детальный сравнительный отчёт по API операциям до 32KB: doc/api/benchmark-comparison-2026-04-12.md
Проблема 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 в текущей инфраструктуре.
- внешние ссылки для повторного разбора сохранены в
doc/thinking/2026-04-12.md,doc/errors/65kb-payload-timeout-2026-04-11.mdиdoc/decisions/message-size-limit-2026-04-11.md.
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
- Глобальный мьютекс — SyncQueues.Lock() на весь сервис. При >50 rps — bottleneck. Стресс-тест подтвердил: работает корректно (нет deadlock/race), но сериализует все операции.
- Нет DLQ — сообщения после maxReceiveCount не перемещаются. Для production — must-have.
- Long Polling наивный — polling каждые 100ms. При 20 клиентах = 200 poll/sec на пустую очередь.
- Нет rate limiting — один тенант может degradировать сервис для остальных.
- Single pod — replicas > 1 не работает из-за глобального мьютекса (два пода = два state).
- Нет метрик — Prometheus exporter отсутствует.
- 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
# Kubernetes
kubectl apply -k deployments/k8s/
# Docker (local)
docker run -p 9090:9090 naeel/shared-sqs:v0.1.14
Last updated: 2026-04-10