98 lines
5.1 KiB
Markdown
98 lines
5.1 KiB
Markdown
# 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`
|