14 KiB
МАНУАЛ: что делать дальше (состояние на 2026-10-08)
Файл для НОВОГО чата. Прочитай его первым, затем документы из раздела 2. Репозиторий:
/home/naeel/nubes/SQS_und_IoT/SQS-service(сервисshared-sqs). Всё, что описано как «сделано», уже в веткеmainи на сервере (origin/main).
1. Где мы сейчас
Код SQS готов и запушен. Ветка main = origin/main, рабочая копия чистая.
Что сделано за 2026-10-05…08:
- закрыт весь план доработок P0/P1/P2 (
doc/thinking/plan-for-flash-2026-10-05.md); - P1.2 — индексация сообщений (tombstone + индексы + амортизированная компакция);
- полный код-ревью сервиса + исправления (утечка блокировки очереди, DLQ в батче,
гонка лимита тенантов, потеря
NubesSub, общий HTTP-клиент); - интеграционные прогоны:
api_test.sh22/22,sdk_test.py15/15,fifo_dlq_probe.py— PASS, стресс 3×2000 сообщений — без зависаний.
Прод-сервис никто не использует (podтверждено владельцем), IoT переделывается с нуля. Поэтому мы свободны менять архитектуру без обратной совместимости.
2. Документы, которые надо прочитать в этом порядке
| Документ | Что внутри |
|---|---|
doc/thinking/architecture-analysis-2026-10-08.md |
ГЛАВНЫЙ: решения по размещению и разбиению (публичный SQS, обход через ВМ, модульный монолит data-plane/control-plane) |
doc/thinking/nubes-large-body-workaround-findings-2026-10-08.md |
как та же болезнь платформы обойдена в ~/nubes/drhider (буфер на ВМ, pull вместо push) — со ссылками «файл:строка» |
doc/thinking/nubes-workaround-applicability-to-sqs-2026-10-08.md |
применимость к SQS: 4 варианта, обязательные замеры, техусловия (Host для подписи, внешние QueueUrl, TLS) |
HISTORY/2026-10-07-session-log.md |
журнал правок: что и почему менялось, найденные дефекты, уроки |
doc/thinking/nubes-ticket.md |
исходная диагностика сетевой болезни (MSS/MTU + таймер шлюза). Тикет отправлять не нужно — см. HANDOFF-NEW-CHAT.md, раздел 7 |
doc/thinking/plan-for-flash-2026-10-05.md |
исходный план доработок (выполнен) |
HANDOFF-NEW-CHAT.md |
доступы, креды, конфигурация кластера, история проекта |
3. Принятые решения (не пересматривать без причины)
- SQS — публичный сервис, как AWS SQS / YMQ. Внешний доступ обязателен, совместимость с AWS SDK — обязательна.
- Сетевую болезнь платформы не «лечим» тикетом — обходим: публичная точка входа на ВМ, минуя managed-шлюз.
- Пока — ВМ (сейчас
5.172.178.213), потом отдельная прод-ВМ. Девопсов не дёргаем, пока не отлажено; затем — уже с доказательствами (tcpdump, период 31–33 с, MSS 1448). - «Без монолитов» = модульный монолит: в отдельные процессы выносим только то, что живёт по-разному. Для SQS граница одна: data-plane (очереди/сообщения/SigV4) и control-plane (тенанты, креды, админ). Биллинг/метрики/UI — модули, не сервисы.
- Ограничение, которое важнее разбиения: ядро очередей держит состояние в памяти одного пода → одиночка. Пока хранилище не вынесено, «не монолит» ≠ «масштабируется».
4. План работ (порядок обязателен)
Шаг 1. Проверить гипотезу на ВМ — БЕЗ кода (критерий входа: домен и сертификат)
Цель: убедиться, что на ВМ болезни нет, до вложений в разбиение.
- Собрать бинарник:
make build(илиCGO_ENABLED=0 go build -o shared-sqs ./app/cmd/). - Поднять на ВМ (memory-only достаточно): см. команды в разделе 5.
- Поставить nginx с TLS на выбранный домен, проксировать на
127.0.0.1:4100. Обязательноproxy_set_header Host $host;— иначе AWS-подпись не сойдётся (сервис берёт хост из запроса:app/auth/auth_middleware.go:315-317). - Замерить с внешней машины (не с ВМ): малые тела, 1 КБ, 10 КБ, 100 КБ, 256 КБ,
плюс длинный прогон на таймауты. Инструменты:
tests/tcp_mtu_probe.py,tests/long_compare_local.py,tests/compare_ymq_vs_shared.py. - Критерий успеха: 0 зависаний ~51 с, 0 таймаутов 31–33 с.
Если гипотеза не подтвердится — СТОП, вернуться к разбору (раздел 2, документ о применимости).
Шаг 2. Код: разбиение на два процесса
data-plane— SQS API и очереди (app/gosqs/*,app/router/router.go,app/auth/auth_middleware.go).control-plane— админка (app/admin/admin.go) и управление тенантами (app/tenant/*).- Что уже учитывать при разбиении:
- адреса очередей формируются жёстко:
app/gosqs/tenant_helpers.go:29-37→http://{region}.{host}:{port}/{tenantID}/{queue}; хост/порт только изapp/conf/goaws.yaml(app/conf/config.go:87-90), env-переменных для Host нет → внешниеQueueUrlпотребуют правки; - подпись SigV4 считается по заголовку
Host(см. выше); - ключ очереди —
{accessKey}:{queueName}(app/gosqs/tenant_helpers.go:15).
- адреса очередей формируются жёстко:
Шаг 3. Код: вынести состояние (стратегический пункт)
- Сейчас: память — источник истины, Redis — write-through (
app/persistence/redis.go,LoadAllQueues), восстановление при старте. - На ВМ поставить Redis и решить, как читать: остаться write-through или перейти к Redis как источнику истины (тогда появится возможность нескольких экземпляров).
- Это решение определяет потолок сервиса (сейчас — один под).
Шаг 4. IoT — отдельно, после SQS
- Внешний MQTT-канал неизбежен (устройства), но там только мелкая телеметрия; критичен разрыв wss ~150 с (лечится переподключением).
- Крупные тела устройств через managed-шлюз не пускать (лимит/дробление/приём на ВМ).
- IoT переделывается с нуля не монолитом: bridge (MQTT), consumer (→storage), API.
5. Команды (проверены)
Локальный запуск (memory-only, без Redis):
cd /home/naeel/nubes/SQS_und_IoT/SQS-service
go build -o /tmp/shared-sqs ./app/cmd/
SHARED_SQS_SEED_DEMO=true /tmp/shared-sqs --admin-token=dev-token-123 --port=4100
# креды демо-тенанта печатаются в лог при старте
⚠️ Не запускать через | head — SIGPIPE убивает процесс на середине теста.
Проверки кода:
go build ./... && go vet ./... && go test -race ./app/...
Деплой на ВМ:
- зеркало репозитория:
naeel@5.172.178.213:~/terra/SQS-service; - SSH:
ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213; - ⚠️ порт 443 на 213 занят (nginx/xray/hysteria), поэтому публичная точка SQS — отдельный домен на существующем nginx (виртуальный хост/SNI) или отдельный порт;
- ⚠️ в образе
DockerfileзашитREDIS_ADDRвнутреннего кластера — на ВМ переопределить (или не задавать, чтобы работать memory-only).
Сборка образа (если через Docker): make docker-build (Makefile, образ naeel/shared-sqs).
6. Грабли и правила (не наступать повторно)
app/cmdв.gitignore→ при добавлении файловgit add -f app/cmd/....deployments/в этом репозитории нет — не искать.Queue.Messages— tombstone-хранилище: менять только черезAppendMessage/RemoveIndex/Compact/Reset; число живых =queue.LiveCount(), а НЕlen(queue.Messages)(app/models/models.go).- После
GetLocked/GetRLocked—defer Unlockдо любыхreturn(иначе очередь зависает навсегда; было вreceive_message.go, исправлено). - Интеграционные тесты:
tests/api_test.shчитаетENDPOINT, python-тесты —ENDPOINT_URL.boto3в системе нет (PEP 668) → скачать колесаpip download boto3, распаковать в/tmpи запускать сPYTHONPATH. - Лимит очередей тенанта = 10 → после упавших прогонов чистить очереди.
- Диагностика зависаний сервиса: стек горутин по
kill -QUIT(SIGQUIT). - Правки ingress на платформе — только через
ShturvalServiceConfig(kubectl откатывает ArgoCD).
7. Правила работы с владельцем (обязательные)
- Коммитить после каждой логически завершённой правки; пуш — только по прямой команде.
- Документировать всё, включая собственные ошибки (HISTORY +
doc/thinking/). - Не выполнять
terraform apply/destroy, не менять платформу, не удалять инстансы. - Не расширять область работ; не лезть в соседние репозитории без прямой команды.
- Рекомендация без замера — не рекомендация, а догадка: сначала мерить, потом предлагать.
- Вопрос от владельца = только ответ (ничего не делать, пока не последует команда).
8. Открытые вопросы (нужны решения владельца)
- Домен и сертификат для публичной точки SQS на ВМ (порт 443 занят → виртуальный хост?).
- Отдельная прод-ВМ — когда создавать и с какими параметрами (пока хватит 213 для тестов; хватит ли 213 — проверить замером: ядра, память, диск, загрузка).
- Redis на ВМ — ставить сейчас или пока memory-only.
- Вынос состояния (Шаг 3) — когда начинать; это определяет масштабируемость.
- Клиенты без явного
endpoint_url— есть ли такие (влияет на внешниеQueueUrl).
9. Карта кода (что где)
| Путь | Ответственность |
|---|---|
app/cmd/goaws.go |
точка входа, флаги, загрузка конфига, periodic tasks, HTTP-сервер |
app/router/router.go |
HTTP-роутинг, лимит тела 3 МБ, биллинг/метрики по операциям |
app/auth/auth_middleware.go |
SigV4 (header + presigned), извлечение тенанта |
app/auth/jwt.go, app/auth/cache.go |
валидация JWT через внешний API + кэш |
app/gosqs/* |
SQS-операции (send/receive/delete/visibility/queue/attributes/tags) |
app/gosqs/receive_message.go |
long-polling, выдача сообщений (в т.ч. per-queue лок) |
app/gosqs/gosqs.go |
фоновый тик: retention, дедупликация, видимость, DLQ |
app/models/models.go |
Queue/SqsMessage, индексация (tombstone), FIFO-состояние |
app/models/globals.go |
SyncQueues: map очередей + tenant-индекс + блокировки |
app/persistence/redis.go |
write-through в Redis, загрузка при старте, переподключение |
app/admin/admin.go |
админка (тенанты/очереди/сообщения), UI-API по JWT |
app/tenant/tenant_store.go |
хранилище тенантов, генерация кредов, авто-провижининг по JWT |
app/billing/billing.go |
учёт операций в PostgreSQL (воркер + буфер) |
app/metrics/* |
Prometheus-метрики и gauge-обновление |
app/conf/goaws.yaml |
Host/Port/Region, дефолты очередей (используется для URL) |
tests/* |
интеграционные проверки (aws CLI, boto3, пробы сети/MTU) |