build: лимиты ресурсов, прокси и нагрузочный тест; docs: API
- docker-compose: cpus/mem_limit через API_CPUS/API_MEM_LIMIT, прокси gost в профиле loadtest - tests/loadtest.py: параллельные запросы к /v1/solve + пики docker stats - docs/API.md: справочник по запросу, действиям, ответу и сессиям - docs/Deployment.md: результаты замеров и правило подбора BROWSER_SLOTS Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
df108dae3f
commit
a319b81d8b
6 files changed
+330
-105
No files matched your search
@@ -46,9 +46,47 @@ docker compose exec api sh -c 'rm -rf /app/extra/user_data_dir/*'
|
||||
|
||||
- `shm_size: 2gb` — Chrome активно использует `/dev/shm`, дефолтных 64 МБ не хватает (вкладки падают с «Aw, Snap»).
|
||||
- `API_PORT` — порт на хосте (по умолчанию 8000): `API_PORT=8001 docker compose up -d`.
|
||||
- `API_CPUS` / `API_MEM_LIMIT` — потолок ресурсов контейнера (по умолчанию 4 CPU / 8 ГБ, swap выключен).
|
||||
При переборе памяти OOM-killer убивает процесс Chrome внутри контейнера, хост не страдает.
|
||||
- `restart: unless-stopped`.
|
||||
- `.env` подключается, если существует (шаблон — `env.example`).
|
||||
|
||||
## Нагрузка
|
||||
|
||||
Замер: `freelancehunt.com/projects` за Cloudflare Turnstile, `captcha_type: cloudflare`, ожидание списка проектов,
|
||||
каждый запрос — новый профиль. Прокси — `gost` из профиля `loadtest`. Хост: 16 ядер, 31 ГБ.
|
||||
|
||||
| Лимит | Параллельно | Успешно | Медиана, с | Пик CPU | Пик RAM |
|
||||
|---|---|---|---|---|---|
|
||||
| 4 CPU | 1 | 1/1 | 5 | 3,5 ядра | 0,5 ГБ |
|
||||
| 4 CPU | 5 | 3/5 | 68 | 4,1 | 2,8 ГБ |
|
||||
| 4 CPU | 10 | 4/10 | 229 | 4,2 | 6,0 ГБ |
|
||||
| 4 CPU | 15 | 3/15 | 261 | 4,2 | 6,1 ГБ |
|
||||
| 12 CPU | 3 | 3/3 | 8 | 7,2 | 1,4 ГБ |
|
||||
| 12 CPU | 5 | 4/5 | 8 | 12,1 | 2,4 ГБ |
|
||||
| 12 CPU | 10 | 9/10 | 23 | 12,3 | 4,7 ГБ |
|
||||
|
||||
Выводы:
|
||||
|
||||
- Узкое место — **CPU**. Один Chrome на прохождении Turnstile съедает 2–3,5 ядра. Когда процессора не хватает,
|
||||
время растёт в десятки раз, а Cloudflare перестаёт пропускать (на 4 CPU и 10 параллельных — 6 из 10 застряли
|
||||
на челлендже).
|
||||
- Память — около **0,5–0,6 ГБ** на браузер.
|
||||
- Правило подбора: `BROWSER_SLOTS ≈ число ядер`, `API_MEM_LIMIT ≈ 0,6 ГБ × BROWSER_SLOTS + 1 ГБ`.
|
||||
Пример: сервер 4 ядра / 8 ГБ → 3–4 слота; сейчас `BROWSER_SLOTS = 10` зашит в `src/main.py` и рассчитан
|
||||
на ~10–12 ядер.
|
||||
- Сверх `BROWSER_SLOTS` запросы сразу получают `No slots available`, не ставятся в очередь.
|
||||
|
||||
Повторить замер:
|
||||
|
||||
```bash
|
||||
API_PORT=8001 docker compose --profile loadtest up -d
|
||||
python tests/loadtest.py --api http://127.0.0.1:8001 --levels 1 5 10
|
||||
```
|
||||
|
||||
Параметры скрипта: `--url`, `--selector`, `--captcha-type`, `--proxy`, `--levels`. Каждый запрос создаёт новый профиль
|
||||
в `extra/user_data_dir` — после прогона их стоит почистить.
|
||||
|
||||
## Reverse proxy
|
||||
|
||||
В проде контейнер ставится за Caddy (TLS). Пример `Caddyfile`:
|
||||
|
||||
Reference in new issue
Block a user