chore: нагрузочный замер v2, push образов в реестр (#86, #85)

- loadtest: у каждого запроса своя сессия, режим --mode v2 (задача + опрос),
  X-API-Key; замер v1/v2 в docs/Deployment.md.
- make push ver=... — образы robotex-api и robotex-worker в docker.sokolab.xyz;
  prod-compose и make release ссылаются на образы реестра.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
protokeyandClaude Opus 5.5 committed 2026-10-13 22:02:59 +04:00
1 parent 1a4bd8d672
commit 11ba83140d
4 files changed
+86 -23

No files matched your search

+27 -5
View File
@@ -147,17 +147,39 @@ docker compose exec worker sh -c 'rm -rf /app/extra/user_data_dir/*'
- Удерживаемые окна (`browser_idle_timeout`) занимают слоты, но почти не тратят CPU.
- Сверх `BROWSER_SLOTS` задачи v2 ждут в очереди, а `/v1/solve` сразу получает `503` с `code: no_slots`.
Замеры выше сделаны на v1 (один сервис, Chrome в api); схема нагрузки на Chrome с очередью та же.
Замеры выше сделаны на v1 (один сервис, Chrome в api).
Повторить замер:
### Замер v2 (очередь, 2026-10-13)
Те же условия: freelancehunt за Cloudflare Turnstile, каждый запрос — новая сессия, прокси `gost`. Воркер:
4 CPU, 8 ГБ, `BROWSER_SLOTS=4`. Хост: 16 ядер.
| Режим | Параллельно | Успешно | Медиана, с | Всё, с | Пик CPU | Пик RAM | Прочее |
|---|---|---|---|---|---|---|---|
| `/v1/solve` | 1 | 1/1 | 7 | 7 | 2,5 ядра | 0,6 ГБ | |
| `/v1/solve` | 4 | 4/4 | 40 | 42 | 4,2 | 2,1 ГБ | |
| `/v1/solve` | 8 | 4/8 | 41 | 42 | 4,2 | 2,2 ГБ | 4 — сразу `503 no_slots` |
| `/v2/tasks` | 4 | 3/4 | 40 | 144 | 4,2 | 2,2 ГБ | 1 застрял на Cloudflare |
| `/v2/tasks` | 8 | 8/8 | 72 | 157 | 4,2 | 2,2 ГБ | лишние 4 ждали в очереди |
Выводы:
- Очередь работает как задумано: сверх слотов v1 отказывает сразу, v2 ставит задачи в очередь и выполняет все.
- Узкое место прежнее — CPU: 4 одновременных прохождения Cloudflare на 4 ядрах идут ~40 с вместо 7. Если почти
все задачи проходят Cloudflare, ставьте `BROWSER_SLOTS ≈ ядер / 2`; удерживаемые окна (`browser_idle_timeout`)
CPU почти не тратят, под них слоты можно добавить.
Повторить:
```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
make key-create name=load
python tests/loadtest.py --api http://127.0.0.1:8001 --api-key rbx_... --levels 1 4 8
python tests/loadtest.py --api http://127.0.0.1:8001 --api-key rbx_... --mode v2 --levels 4 8
```
Параметры скрипта: `--url`, `--selector`, `--captcha-type`, `--proxy`, `--levels`. Каждый запрос создаёт новый профиль
в `extra/user_data_dir` — после прогона их стоит почистить.
Параметры скрипта: `--mode v1|v2`, `--api-key`, `--url`, `--selector`, `--captcha-type`, `--proxy`, `--levels`.
Каждый запрос создаёт новый профиль в `extra/user_data_dir`; воркер удалит их через `PROFILE_TTL_DAYS`.
## Reverse proxy