docs: finalize 64kb ingress investigation
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user