diff --git a/lps/docs/architecture.md b/lps/docs/architecture.md index 1f80650..79ecc6e 100644 --- a/lps/docs/architecture.md +++ b/lps/docs/architecture.md @@ -95,7 +95,15 @@ - `POST /search`에 상품 리스트를 주면 상품마다 잡을 큐에 적재. - 워커 동시성(`WORKER_CONCURRENCY=N`)만큼 상품을 **진짜 병렬** 처리 — 워커마다 **자기 브라우저 세트**(프로필 분리 + 다른 프록시 IP)를 가져 공유 lock 병목을 없앰. 권장 N=2~3(로컬, Chrome 최대 4×N개). -- 부하 측정: `loadtest.py`(처리량·p50/p95 지연·AI/DECODO/총비용 집계). +- 부하 측정: `loadtest.py`(e2e 처리량·p50/p95 지연·AI/DECODO/총비용) · `loadtest/`(Locust API 부하, 멀티코어 벤치). + +### 6-1. API 멀티코어 스케일 & 커넥션 풀 자동산정 + +- **API 서버는 asyncio(스레드 1개) = 1 프로세스 1 코어**. 처리량을 코어만큼 올리려면 `process_count`(uvicorn 워커 수)를 늘린다. +- **함정**: 프로세스마다 독립 커넥션 풀을 열어 `(pool_size + max_overflow) × 2엔진(R/W) × process_count` 만큼 커넥션을 요구 → PG `max_connections`(기본 100)를 넘으면 **커넥션 고갈로 요청 실패 폭증**(부하테스트로 실증: 풀 10/20 · 4프로세스 = 240 요구 → 실패 1만+). +- **해결(자동)**: `MainDBConfig.connection_budget`(기본 40)를 두면 기동 시 `process_count`에 맞춰 `pool_size/max_overflow`를 **역산**해 `(pool+overflow)×2×process_count ≤ budget`을 스스로 보장(`server_configs._autosize_pool`). 워커를 늘려도 예산을 넘지 않는다. 기동 로그 `DB Pool : … = N conns (budget=…)`로 실효값 확인. +- **예산 가이드**: 공유 PG=40(API+worker+타 서비스 공존, 안정 우선) / 전용 PG(`max_connections≈100`)=90(처리량 우선). env `DB_CONNECTION_BUDGET`. 더 큰 처리량은 예산↑ + PG `max_connections`↑ 또는 pgbouncer. +- 상세·벤치 결과: [`../loadtest/README.md`](../loadtest/README.md). ## 7. 최저가 이력 (그래프)