docs(lps): 워커·브라우저 1:1 근거와 워커 수 상한 산정법 문서화
- 6-2: 브라우저가 아니라 신원(프로필+sticky IP)이 희소 자원인 이유, 비율이 어긋날 때의 손해(유휴 낭비 vs 락 직렬화), 신원당 처리량 캡 - 6-3: 워커 상한 = min(RAM캡, 포트캡÷3, 실측 정체점) — 하드캡 계산식과 계단식 실측 시 멈춤 신호 5가지(처리량 정체·blocks_1h·메모리· 단일코어 포화·p95) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
463416c3a2
commit
4381649658
@ -107,6 +107,57 @@
|
||||
- **예산 가이드**: 공유 PG=40(API+worker+타 서비스 공존, 안정 우선) / 전용 PG(`max_connections≈100`)=90(처리량 우선). env `DB_CONNECTION_BUDGET`. 더 큰 처리량은 예산↑ + PG `max_connections`↑ 또는 pgbouncer.
|
||||
- 상세·벤치 결과: [`../loadtest/README.md`](../loadtest/README.md).
|
||||
|
||||
### 6-2. 왜 브라우저는 워커당 1세트인가 (더 띄우면 안 되나?)
|
||||
|
||||
Chrome 프로세스 자체는 얼마든지 더 띄울 수 있다. 그런데도 워커:브라우저를 1:1로 두는 이유 —
|
||||
정확히는 **"더 띄워봐야 이득이 0이고, 덜 띄우면(공유하면) 손해"**라서 1:1이 낭비도 병목도 없는 균형점이다.
|
||||
|
||||
- **희소 자원은 브라우저가 아니라 "신원(identity)"**. 쿠팡용 브라우저 1개 = Chrome 프로필(Akamai 쿠키,
|
||||
cf_clearance) + DECODO sticky IP(포트) 묶음이다. Akamai 는 쿠키와 IP 를 묶어 보므로(불일치 시 재챌린지)
|
||||
브라우저 추가 = 웜업 챌린지 1회 추가 + 프록시 포트 1개 소모 + 봇 감지 노출면 확대다. Chrome 은 공짜여도
|
||||
**쓸 수 있는 신원은 공짜가 아니다.**
|
||||
- **검색 1건은 브라우저 여러 개로 못 쪼갠다.** 검색은 "페이지 열고 → 렌더 대기 → 파싱"의 순차 작업.
|
||||
병렬화 단위는 검색이 아니라 **잡(=상품)**이고, 잡의 동시 처리 주체가 워커다. 워커는 소스당 검색을
|
||||
한 번에 하나만 하므로 소스당 브라우저 1개면 항상 꽉 채워 쓴다.
|
||||
- **비율이 어긋나면**: 브라우저 > 워커 → 남는 브라우저는 놀면서 메모리·포트·웜업 비용만 차지(처리량 +0).
|
||||
브라우저 < 워커(공유) → 어댑터가 브라우저 상태(페이지·봇감지 회전 상태머신) 때문에 검색을 락으로
|
||||
직렬화하므로 사실상 순차가 된다(2026-07-10 스톨 사건이 정확히 이 모습 — 웜업이 락을 쥐자 그 워커의
|
||||
검색 전체가 정지).
|
||||
- **처리량 상한도 브라우저 수가 아니다.** 신원 하나당 요청 간격을 일부러 2~8s 랜덤으로 벌린다(등간격
|
||||
기계 요청 = 탐지 신호). 즉 신원당 처리량은 설계상 캡 — 처리량을 올리는 유일한 방법은 신원(=워커)을
|
||||
늘리는 것이다.
|
||||
|
||||
### 6-3. 워커 수 상한을 서버에서 파악하는 법
|
||||
|
||||
`워커 상한 = min( RAM캡, 포트캡, 실측 정체점 )` — 계산 가능한 하드캡 2개로 범위를 좁히고, 그 안에서 계단식 실측.
|
||||
|
||||
**하드캡(계산)**
|
||||
|
||||
- **RAM캡** = `(전체 RAM − OS/PG/API 여유분) × 0.7 ÷ 세트당 RSS`.
|
||||
세트당 RSS 는 워커 N개로 부하를 건 상태에서 chrome 프로세스 그룹 RSS 합 ÷ N (모니터 :9700 의
|
||||
프로세스 그룹, 정밀하게는 `ps` RSS 합산). headful Chrome 세트는 리소스 차단을 해도 세트당
|
||||
수백 MB~1GB — 16GB 서버면 대략 8~12세트에서 걸린다. 폴백을 켜면 워커당 브라우저 최대 4개로 배수 증가.
|
||||
- **포트캡** ≈ `DECODO 포트 수 ÷ 3`. 워커마다 다른 sticky 포트가 필요하고 봇 감지 시 다음 포트로
|
||||
회전하므로 회전 여유분이 필수 — 워커 수가 포트 수에 근접하면 회전 후 옆 워커가 쓰던 IP 를 받는
|
||||
충돌이 생긴다. `config` 의 `port_start~port_end`에서 바로 계산.
|
||||
|
||||
**소프트캡(실측 — 보통 이게 진짜 상한)**
|
||||
|
||||
`WORKER_CONCURRENCY` 3→6→9… 계단으로 올리며 매번 같은 부하(`N=30 loadtest.py` 등)를 걸고,
|
||||
아래 신호 중 **먼저 오는 것**이 그 서버의 상한:
|
||||
|
||||
1. **처리량 정체** — 워커 2배인데 상품/분이 2배가 안 됨(리포트 숫자로 비교).
|
||||
2. **봇 감지율 급증** — `blocks_1h`가 워커 수보다 가파르게 상승. 프록시 재시도 비용+차단 리스크라
|
||||
CPU 보다 먼저 멈춰야 하는 신호.
|
||||
3. **메모리 압박** — macOS `memory_pressure` / Linux swap 시작. Chrome 은 부족하면 느려지는 게 아니라 크래시.
|
||||
4. **워커 파이썬 프로세스의 단일 코어 포화** — 워커 N개는 **파이썬 프로세스 1개 안의 asyncio 태스크**라
|
||||
파이썬 쪽 일(파싱·AI 응답 처리·DB)은 코어 1개를 공유한다. 모니터에서 worker 프로세스가 코어 1개
|
||||
기준 100%에 붙으면 그 이상은 무의미. (Chrome 들은 별도 프로세스라 나머지 코어로 퍼진다.)
|
||||
5. **p95 지연 상승** — 상품당 지연이 워커 늘리기 전보다 나빠지면 경합(락·프록시·DB) 시작.
|
||||
|
||||
한 서버의 실측 상한을 넘는 처리량이 필요하면 워커 컨테이너를 **수평 확장**한다(§1 — 큐 기반이라
|
||||
워커만 늘리면 됨. `Dockerfile.worker` + compose).
|
||||
|
||||
## 7. 최저가 이력 (그래프)
|
||||
|
||||
- **트리거 기반**: 자동 배치 없이 **실제 조회된 상품만** 그 시점에 기록 → 트래픽·비용 절약.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user