# Применимость обхода из drhider к shared-sqs (разбор) **Дата:** 2026-10-08 **Основание:** `nubes-large-body-workaround-findings-2026-10-08.md` (находки из `~/nubes/drhider`). **Статус:** анализ. **Ничего ещё не внедрено** — сначала замеры (см. раздел 5). --- ## 1. Почему нельзя скопировать схему 1:1 В drhider обе стороны протокола — свои (браузер + своё приложение на Flask), поэтому туда встроили двухшаговый протокол: `PUT` файла на ВМ-буфер → `POST` ссылки в кластер → исходящий `GET` (pull). В shared-sqs **обе стороны чужие по протоколу**: клиенты — сторонние приложения с AWS SDK (подпись SigV4), протокол SQS синхронный (запрос → ответ). Вставить «положите тело на буфер, пришлите ссылку» нельзя без изменения клиентов и потери совместимости с AWS SDK. → Прямой аналог буфера в SQS — **прозрачный обратный прокси на ВМ**, а не буфер и не хранилище. Данные идут потоком, протокол не меняется. ## 2. Что именно болит у shared-sqs (наши факты) | Явление | Причина по нашим документам | Источник | |---|---|---| | A. Большие тела (>~1.4 КБ) виснут ~51 с | MSS, анонсируемый шлюзом = 1448; MTU пода 1400, underlay 1450 → сегменты 1488 дропаются при DF; PMTUD мёртв (ICMP не доходит) | `nubes-ticket.md:11-13` | | B. Малые тела (512 Б) — `ReadTimeout` 30 с с периодом 31–33 с | таймер на ВНЕШНЕМ шлюзе; доказано tcpdump: запросы не доходят до пода, nginx чист, Cilium 0 дропов | `nubes-ticket.md` (явление B), HANDOFF | Что уже проверено ранее: - **внутри кластера** — проблем нет; **с ВМ (5.172.178.213) p50 = 6–8 мс, таймаутов нет**; - **MTU пода уже 1400** — то есть тот фикс, который помог drhider (1500→1400), у нас **уже применён**, а явление A осталось: причина в MSS-анонсе шлюза, а это вне нашего контроля (`nubes-ticket.md:16-17`); - лимит SQS — тело ≤ 262144 Б (256 КБ), т.е. большие тела легальны и попадают ровно в проблемную зону. ## 3. Варианты, применимые к SQS ### Вариант 1 (основной) — публичная точка входа на ВМ-прокси Схема: `клиент (AWS SDK) → HTTPS на ВМ → nginx (ВМ) → под shared-sqs в кластере`. Убираем из пути внешний шлюз платформы. Основания: - путь «интернет → ВМ» в drhider держал тела 63 КБ и 5 МБ **успешно** (`PROBLEM-AND-SOLUTION.md`), то есть у ВМ нет той патологии, что у шлюза кластера; - путь «ВМ → кластер» у нас измерен: 6–8 мс, таймаутов нет. **Технические условия (важные, иначе не заработает):** 1. **SigV4 подписывает заголовок `Host`.** nginx обязан передавать внешний хост: `proxy_set_header Host $host;`. Сервис берёт хост именно из запроса — `auth_middleware.go:315-317` (`canonicalHeaderValue`: `name == "host"` → `r.Host`). Подменять Host на внутренний (например, на служебное имя сервиса) **нельзя** — подпись перестанет сходиться, клиент получит `SignatureDoesNotMatch`. 2. **URL очередей сейчас жёстко внутренние и без TLS.** `tenantQueueURL` (`tenant_helpers.go:29-37`) формирует `http://{region}.{host}:{port}/{tenantID}/{queue}`. Хост и порт читаются **только из `goaws.yaml`** (`conf/config.go:87-90`; в `applyEnvironmentDefaults` env-переменных для Host нет). Следствия: - клиенты, которые сами задают `endpoint_url` (все наши тесты), берут из `QueueUrl` только путь — они не пострадают; - клиенты **без** `endpoint_url` пойдут на хост из `QueueUrl` → обязаны получить внешний адрес. Значит: либо (а) подставляем внешний хост/схему в конфиг, либо (б) nginx переписывает `QueueUrl` в ответах (хрупко), либо (в) требуем от клиентов явный `endpoint_url`. 3. **Транспорт.** Схема `http://` в URL — при переносе на ВМ либо оставляем `http` (нежелательно для интернета), либо переводим на `https` и правим формирование URL. Для TLS нужен сертификат на ВМ-домен. 4. **Доступ ВМ → кластер.** ВМ вне кластера; понадобится NodePort/VIP (или опубликованный внутренний адрес). Путь ВМ→кластер нужно замерить (см. раздел 5). 5. **Проксирование тел** — без буферизации на диск: `proxy_request_buffering off`, `client_max_body_size` ≥ 256 КБ (+ запас). ### Вариант 2 — настройки ingress через `ShturvalServiceConfig` В drhider этим вылечили RST (`keep-alive: 10` → `75`), подняли `proxy-body-size: 1024m`, выключили HTTP/2, подняли `client-body-timeout: 60`. Правки делаются **только через `ShturvalServiceConfig`** — kubectl откатывает ArgoCD (`PROBLEM-AND-SOLUTION.md`). Оценка для нас: **скорее всего не поможет**. Наш таймер (явление B) доказанно находится **вне кластера** (tcpdump: запросы не доходят до пода; nginx чист), а MSS-анонс делает **внешний шлюз**. Но правка дешёвая и безопасная → имеет смысл проверить замером «до/после», прежде чем строить прокси. ### Вариант 3 — MTU-фикс **Уже сделан** (MTU пода 1400). Явление A не убрал — так как причина в шлюзе. Для SQS этот путь закрыт. ### Вариант 4 — клиентские ретраи (+ идемпотентность) Маскирует явление B, **не решает** явление A (51 с ожидания при большом теле). Для standard-очередей ретрай без идемпотентности даёт дубли (FIFO-дедуп по `MessageDeduplicationId` у нас есть, для standard — нет). Годится как временная мера, не как решение. ## 4. Сводка: что какой вариант лечит | Вариант | Явление A (большие тела) | Явление B (таймер) | Стоимость/риск | |---|---|---|---| | 1. Прокси на ВМ | да (по аналогии с drhider) | да (шлюз вне пути) | TLS, Host, внешние URL, доступ ВМ→кластер | | 2. Настройки ingress | вероятно нет | вероятно нет | низкая; нужен доступ к платформенному конфигу | | 3. MTU | нет (уже 1400) | нет | — | | 4. Ретраи клиентов | нет | частично | дубли для standard | ## 5. Что обязательно замерить ДО решения Правило проекта: рекомендация без замера — догадка. Замеры на том же хосте и тем же инструментом: 1. **С ВМ → внешний endpoint кластера**: тела 1 КБ / 10 КБ / 100 КБ / 256 КБ — есть ли ~51 с? (Малые тела с ВМ проверены: 6–8 мс, таймаутов нет; большие, судя по всему, отдельно не мерили.) 2. **ВМ → кластер (NodePort/VIP)**: те же размеры — сколько занимает. 3. **Явление B с ВМ**: сохраняется ли период 31–33 с. 4. **После варианта 2** (если включаем): те же замеры, сравнение «до/после». Инструменты уже есть в репозитории: `tests/tcp_mtu_probe.py`, `tests/long_compare_local.py`, `tests/compare_ymq_vs_shared.py`, `tests/platform_probe.py`, `tests/reboot_probe.py`. ## 6. Вывод - Тикет в поддержку — **не решение** (болезнь платформы), оставляем только как историю; в drhider её тоже не «починили», а обошли. - Архитектурный аналог решения drhider для SQS — **прозрачный прокси на ВМ** (вариант 1). Ключевые камни: сохранение `Host` для SigV4, внешние `QueueUrl` (сейчас `http://{region}.{host}:{port}` из `goaws.yaml`), TLS, доступ ВМ→кластер. - Перед стройкой — замеры из раздела 5; возможно, вариант 2 закроет часть проблемы за 10 минут вместо новой инфраструктуры. ## 7. Открытые вопросы (нужны твои решения) 1. Внешний домен и сертификат для ВМ-прокси — какой брать? 2. Клиенты без явного `endpoint_url` — есть ли такие (иначе вопрос №3 в разделе 3 отпадает)? 3. Делать ли сначала замеры (раздел 5) — я готов.