Files
SQS-service/MANUAL-NEXT-2026-10-08.md

14 KiB
Raw Permalink Blame History

МАНУАЛ: что делать дальше (состояние на 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.sh 22/22, sdk_test.py 15/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. Принятые решения (не пересматривать без причины)

  1. SQS — публичный сервис, как AWS SQS / YMQ. Внешний доступ обязателен, совместимость с AWS SDK — обязательна.
  2. Сетевую болезнь платформы не «лечим» тикетом — обходим: публичная точка входа на ВМ, минуя managed-шлюз.
  3. Пока — ВМ (сейчас 5.172.178.213), потом отдельная прод-ВМ. Девопсов не дёргаем, пока не отлажено; затем — уже с доказательствами (tcpdump, период 31–33 с, MSS 1448).
  4. «Без монолитов» = модульный монолит: в отдельные процессы выносим только то, что живёт по-разному. Для SQS граница одна: data-plane (очереди/сообщения/SigV4) и control-plane (тенанты, креды, админ). Биллинг/метрики/UI — модули, не сервисы.
  5. Ограничение, которое важнее разбиения: ядро очередей держит состояние в памяти одного пода → одиночка. Пока хранилище не вынесено, «не монолит» ≠ «масштабируется».

4. План работ (порядок обязателен)

Шаг 1. Проверить гипотезу на ВМ — БЕЗ кода (критерий входа: домен и сертификат)

Цель: убедиться, что на ВМ болезни нет, до вложений в разбиение.

  1. Собрать бинарник: make build (или CGO_ENABLED=0 go build -o shared-sqs ./app/cmd/).
  2. Поднять на ВМ (memory-only достаточно): см. команды в разделе 5.
  3. Поставить nginx с TLS на выбранный домен, проксировать на 127.0.0.1:4100. Обязательно proxy_set_header Host $host; — иначе AWS-подпись не сойдётся (сервис берёт хост из запроса: app/auth/auth_middleware.go:315-317).
  4. Замерить с внешней машины (не с ВМ): малые тела, 1 КБ, 10 КБ, 100 КБ, 256 КБ, плюс длинный прогон на таймауты. Инструменты: tests/tcp_mtu_probe.py, tests/long_compare_local.py, tests/compare_ymq_vs_shared.py.
  5. Критерий успеха: 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:16).

Шаг 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. Грабли и правила (не наступать повторно)

  1. app/cmd в .gitignore → при добавлении файлов git add -f app/cmd/....
  2. deployments/ в этом репозитории нет — не искать.
  3. Queue.Messages — tombstone-хранилище: менять только через AppendMessage/RemoveIndex/ Compact/Reset; число живых = queue.LiveCount(), а НЕ len(queue.Messages) (app/models/models.go).
  4. После GetLocked/GetRLocked — defer Unlock до любых return (иначе очередь зависает навсегда; было в receive_message.go, исправлено).
  5. Интеграционные тесты: tests/api_test.sh читает ENDPOINT, python-тесты — ENDPOINT_URL. boto3 в системе нет (PEP 668) → скачать колеса pip download boto3, распаковать в /tmp и запускать с PYTHONPATH.
  6. Лимит очередей тенанта = 10 → после упавших прогонов чистить очереди.
  7. Диагностика зависаний сервиса: стек горутин по kill -QUIT (SIGQUIT).
  8. Правки ingress на платформе — только через ShturvalServiceConfig (kubectl откатывает ArgoCD).

7. Правила работы с владельцем (обязательные)

  • Коммитить после каждой логически завершённой правки; пуш — только по прямой команде.
  • Документировать всё, включая собственные ошибки (HISTORY + doc/thinking/).
  • Не выполнять terraform apply/destroy, не менять платформу, не удалять инстансы.
  • Не расширять область работ; не лезть в соседние репозитории без прямой команды.
  • Рекомендация без замера — не рекомендация, а догадка: сначала мерить, потом предлагать.
  • Вопрос от владельца = только ответ (ничего не делать, пока не последует команда).

8. Открытые вопросы (нужны решения владельца)

  1. Домен и сертификат для публичной точки SQS на ВМ (порт 443 занят → виртуальный хост?).
  2. Отдельная прод-ВМ — когда создавать и с какими параметрами (пока хватит 213 для тестов; хватит ли 213 — проверить замером: ядра, память, диск, загрузка).
  3. Redis на ВМ — ставить сейчас или пока memory-only.
  4. Вынос состояния (Шаг 3) — когда начинать; это определяет масштабируемость.
  5. Клиенты без явного 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)