# Decision: Ограничение MaximumMessageSize — 2026-04-11 ## Update — 2026-04-12 Первичное решение из этой записи было пересмотрено после дополнительного расследования ingress controller штурвала. ### Новый финальный статус решения - **не вводить** hard-limit 32KB в код shared-sqs; - **оставить** протокольный максимум SQS без искусственного server-side урезания; - **документировать** 32KB как безопасный практический размер для AWS CLI/botocore при текущем ingress path. ### Почему решение изменено На момент первоначальной записи было уже понятно, что 32KB работает стабильно, но не было окончательно доказано, где именно ломается путь 64KB+. Дополнительное расследование 2026-04-12 показало: 1. В кластере для `qu.kube5s.ru` существует только один ingress. 2. Объект ingress у shared-sqs содержит `proxy-request-buffering: "off"`. 3. Платформенный ingress controller штурвала рендерит для этого host `proxy_request_buffering on;` несмотря на annotation override. 4. Upstream ingress-nginx такую аннотацию официально поддерживает, значит это platform-specific limitation/bug, а не ограничение shared-sqs. Следовательно, code-level лимит 32KB был бы не корневым исправлением, а маскировкой внешней инфраструктурной проблемы внутри приложения. ## Контекст При тестировании shared-sqs v0.1.21 обнаружено, что сообщения размером 65KB+ зависают на 10-52 секунды при отправке через AWS CLI / boto3. ## Проблема ### Root Cause (подтверждённый) **Цепочка сбоя:** urllib3 2.0 + botocore + TLS + Nagle's algorithm + nginx. 1. **urllib3 2.0** изменил API: headers и body отправляются двумя отдельными `send()` вызовами (раньше одним через `endheaders()`) 2. **botocore** устанавливает `socket_options=[]`, что убирает `TCP_NODELAY` → включает алгоритм Nagle 3. Body (65629 байт) шифруется TLS в 4 записи по ~16KB 4. Первые 3 записи (49152 байт) отправляются сразу 5. Последняя 4-я запись (~16KB) **застревает** из-за Nagle + delayed ACK deadlock 6. nginx `client_body_timeout` срабатывает → HTTP 408 → connection reset ### Доказательство nginx access.log при сбое: ``` POST status=408 req_len=49926 bytes_sent=0 time=10.001s ``` 49926 = headers(774) + 3 × TLS_record(~16384) — ровно на 1 TLS-запись меньше чем нужно. ### Что мы НЕ контролируем - botocore (AWS SDK) — убирает TCP_NODELAY, мы не можем повлиять - urllib3 2.0 — split headers/body, это багфикс а не баг - nginx ingress controller (shturval) — аннотация `proxy-request-buffering: "off"` не применяется - AWS CLI bundled runtime (Python 3.14.3 с другим TLS-стеком) ### Что мы пробовали 1. **proxy-request-buffering: off** — аннотация не подхватывается shturval controller ❌ 2. **client_body_timeout: 120s** — помогло для pip boto3, но НЕ для AWS CLI ❌ 3. **client_body_buffer_size: 2m** — не помогло для AWS CLI ❌ 4. **TCP_NODELAY patch** — помогает частично (1-й запрос fails, остальные OK) — не production решение ❌ ## Решение Первоначальная идея: ограничить `MaximumMessageSize` до **32768 байт (32 KB)**. Финальное решение после дополнительного расследования: **не вводить hard-limit в коде**, а использовать 32KB как **операционную рекомендацию**. ### Обоснование 1. **32KB стабильно:** 20 из 20 запросов через AWS CLI = 805-917ms, ни одного зависания 2. **Двойной запас:** от порога сбоя (64720B) до лимита (32768B) — двойной запас 3. **Покрывает use-cases:** >99% SQS-сообщений — JSON, уведомления, команды (<10KB) 4. **Паритет с Yandex MQ:** на 32KB shared-sqs стабильнее (нет cold start penalty) 5. **Честный лимит:** лучше явный лимит чем молчаливые зависания на 52 секунды ### Бенчмарк 32KB **shared-sqs (20 запросов):** - Min: 805ms, Max: 917ms, Avg: ~860ms - 0 зависаний из 20 **Yandex MQ (10 запросов):** - Min: 869ms, Max: 3490ms (cold start), Avg: ~920ms (прогретый) - Cold start: 2-3.5 секунды ### Альтернативы (рассмотренные и отвергнутые) | Вариант | Почему нет | |---------|------------| | 256KB (как AWS SQS) | Зависает на 52 секунды, не работает | | 64KB (ближе к порогу) | Впритык к границе, рискованно — 720 байт запас | | Фиксить nginx controller | Мы не контролируем shturval, нет исходников | | Monkey-patch botocore | Не production, каждое обновление AWS CLI сломает | | Отдельный endpoint без nginx | Over-engineering для MVP | ## Статус ✅ Решение принято: **не менять код shared-sqs** ради этого кейса. ## Практический вывод 1. Для повседневного использования через AWS CLI/botocore ориентироваться на payload до 32KB. 2. Если в будущем потребуется надёжная поддержка 64KB+ для этих клиентов, исправление нужно делать в platform ingress layer, а не в shared-sqs.