7.6 KiB
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 показало:
- В кластере для
qu.kube5s.ruсуществует только один ingress. - Объект ingress у shared-sqs содержит
proxy-request-buffering: "off". - Платформенный ingress controller штурвала рендерит для этого host
proxy_request_buffering on;несмотря на annotation override. - 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.
- urllib3 2.0 изменил API: headers и body отправляются двумя отдельными
send()вызовами (раньше одним черезendheaders()) - botocore устанавливает
socket_options=[], что убираетTCP_NODELAY→ включает алгоритм Nagle - Body (65629 байт) шифруется TLS в 4 записи по ~16KB
- Первые 3 записи (49152 байт) отправляются сразу
- Последняя 4-я запись (~16KB) застревает из-за Nagle + delayed ACK deadlock
- 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-стеком)
Что мы пробовали
- proxy-request-buffering: off — аннотация не подхватывается shturval controller ❌
- client_body_timeout: 120s — помогло для pip boto3, но НЕ для AWS CLI ❌
- client_body_buffer_size: 2m — не помогло для AWS CLI ❌
- TCP_NODELAY patch — помогает частично (1-й запрос fails, остальные OK) — не production решение ❌
Решение
Первоначальная идея: ограничить MaximumMessageSize до 32768 байт (32 KB).
Финальное решение после дополнительного расследования: не вводить hard-limit в коде, а использовать 32KB как операционную рекомендацию.
Обоснование
- 32KB стабильно: 20 из 20 запросов через AWS CLI = 805-917ms, ни одного зависания
- Двойной запас: от порога сбоя (64720B) до лимита (32768B) — двойной запас
- Покрывает use-cases: >99% SQS-сообщений — JSON, уведомления, команды (<10KB)
- Паритет с Yandex MQ: на 32KB shared-sqs стабильнее (нет cold start penalty)
- Честный лимит: лучше явный лимит чем молчаливые зависания на 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 ради этого кейса.
Практический вывод
- Для повседневного использования через AWS CLI/botocore ориентироваться на payload до 32KB.
- Если в будущем потребуется надёжная поддержка 64KB+ для этих клиентов, исправление нужно делать в platform ingress layer, а не в shared-sqs.
Ссылки для повторного разбора
-
Штурвал Community Edition, архитектура платформы: https://docs.k8s.ngcloud.ru/2.12/docs/common/structure/
-
ingress-nginx annotations: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
-
ingress-nginx configmap: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
-
upstream parser
proxy-request-buffering: https://github.com/kubernetes/ingress-nginx/blob/main/internal/ingress/annotations/proxy/main.go -
upstream e2e tests for proxy annotations: https://github.com/kubernetes/ingress-nginx/blob/main/test/e2e/annotations/proxy.go
Если к вопросу 64KB+ возвращаться позже, эти ссылки нужны для быстрого подтверждения двух вещей:
- ingress controller у нас platform-managed со стороны Штурвала;
- аннотация
proxy-request-bufferingв upstream ingress-nginx поддерживается официально.