Files
loadtest/History/2026-07-10-upload-investigation.md
T
2026-07-10 21:19:31 +04:00

5.1 KiB

2026-07-10 — Полное расследование: почему режутся файлы при загрузке

Симптом

Загрузка файлов > 64KB через веб-интерфейс loadtest обрывается. Даже чанки не проходят.

Диагностика

Тесты

Тест Результат
Изнутри пода (Flask, 100KB base64) 102400 байт, 4ms
Снаружи (curl, 136KB URL-encoded POST) 408 Timeout / Connection reset
Снаружи (Python urllib, 136KB POST) RemoteDisconnected
Маленький POST (12 байт)

Инфраструктура

Клиент → [прокси/LB] → nginx ingress (ModSecurity) → Flask dev-сервер (не Gunicorn!)
  • Платформа: Shturval (managed Kubernetes)
  • Сервис: loadtest.pythonk8s.dev.nubes.ru, IP 185.247.187.151 (NUBES LLC)
  • Namespace: 9039a501-df2c-4b85-b049-9cd4f77e6ac0
  • Deployment: pythonk8s
  • Запуск: python app.py (Flask dev-сервер, НЕ Gunicorn)

ModSecurity в nginx ingress

SecRequestBodyLimit 13107200       # 12.5 MB — общий лимит
SecRequestBodyNoFilesLimit 131072  # 128 KB — лимит для НЕ-файловых полей
SecRuleEngine DetectionOnly        # только логирует, не блокирует

Базовая строка 136KB отправляется как URL-encoded form → попадает под NoFilesLimit.

Ingress-логи

  • Маленькие POST (146 байт) → 200 OK
  • Большие POST (49-65KB) → 408 Timeout через 10 секунд
  • ingress_request_length показывает 49-65KB при отправленных 136KB → тело обрезается ДО ingress (прокси/LB)

Предыдущий опыт (contracts)

Из /home/naeel/nubes/contracts/History/:

session-07-chunks.md (v1.15-1.18)

  • Чанки 50KB FormData → только первый доходит
  • Чанки в PostgreSQL → то же самое
  • 7 отдельных psycopg2.connect на сборку → медленно → таймаут Ingress

session-08-upload-saga.md (v1.12-1.26)

  • 26 версий до рабочей загрузки
  • FormData/multipart →
  • base64 JSON →
  • v1.26: original_bytes DROP NOT NULL + original_b64 TEXT → ✓ РАБОТАЛО
  • Потом регресс на v1.27+

upload-analysis-v40.md (v1.40)

  • request.get_data(as_text=True) + raw regex (без JSON, без b64decode, без БД) → всё равно HTTP 000
  • Redis rpush() под подозрением
  • curl: 100KB — 2/5 HTTP 000, 3/5 HTTP 200 (случайно)

connection-reset-analysis.md (v1.21)

  • HTTP 000 случайно, не зависит от размера
  • Health check (GET) всегда 200
  • Прямой /test (JSON → БД) всегда работает

sonnet-upload-from-scratch.md — ИТОГ

"64KB — жёсткий предел платформы" 43 версии. FormData, JSON/base64, чанки, Redis, retry — ничего не помогло.

Корневая причина

Платформа pythonk8s (Shturval) имеет непреодолимый предел ~64KB на тело POST-запроса. Это не баг приложения — это ограничение инфраструктуры:

  • ModSecurity SecRequestBodyNoFilesLimit = 128KB
  • Прокси/LB перед ingress обрезает тело ещё сильнее (до ~50-65KB)
  • Ingress таймаутит через 10 секунд

Ни base64, ни JSON, ни чанки не обходят этот предел.

Ложная правка

  • Dockerfile: добавлены --limit-request-field_size 0 --limit-request-body 0бесполезно, т.к. Gunicorn не используется
  • site/app.py: версия 1.0.4 → 1.0.5 — задеплоено, но проблему не решает

Что дальше

Для loadtest как инструмента замера скорости загрузки этот предел фатален. Нужно решать на уровне платформы:

  1. Увеличить SecRequestBodyNoFilesLimit в ModSecurity
  2. Убрать/настроить прокси/LB перед ingress
  3. Либо перенести сервис на другую платформу без этих ограничений

Источники

  • /home/naeel/nubes/contracts/History/sessions/session-07-chunks.md
  • /home/naeel/nubes/contracts/History/sessions/session-08-upload-saga.md
  • /home/naeel/nubes/contracts/History/features/upload-analysis-v40.md
  • /home/naeel/nubes/contracts/History/features/upload-analysis-v41.md
  • /home/naeel/nubes/contracts/History/features/connection-reset-analysis.md
  • /home/naeel/nubes/contracts/History/features/chunk-analysis-request.md
  • /home/naeel/nubes/contracts/History/llm-analysis/sonnet-upload-from-scratch.md
  • /home/naeel/nubes/contracts/History/llm-analysis/sonnet-appjs-analysis.md