기존 run_local_server.sh 스타일에 맞춘 대화형 .sh 두 개. - run_local_worker.sh: 동시성(WORKER_CONCURRENCY)·Chrome 프로필(LPS_PROFILE_DIR) 선택 후 워커 기동. 실행 중 워커 감지 시 교체 여부 확인. venv/config 자동 보장. - run_loadtest_gui.sh: Locust 웹 UI(:8089) 기동. 워커 실행 중이면 경고(크롤 비용), API 미기동 시 PROCESS_COUNT 받아 백그라운드 기동(종료 시 함께 정리). 부하생성기 --processes. - .gitignore(lps): .profiles/(Chrome 쿠키·cf_clearance 세션) 커밋 방지 - README·operations: 새 스크립트 안내로 갱신 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
3.9 KiB
Bash
Executable File
85 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# LPS 부하 테스트 — Locust 웹 UI(GUI) 실행 (대화형).
|
|
# 브라우저(:8089)에서 동시 유저 수·spawn rate 를 조절하며 실시간 그래프로 RPS/지연을 본다.
|
|
# 대상 = API 서버(web_main, :9600). enqueue/조회 경로에 부하를 준다.
|
|
#
|
|
# ⚠️ 워커는 끄고 실행하라 — 부하 중 실제 크롤(프록시/AI 비용)이 발생한다.
|
|
# 쌓인 부하 잡 정리: psql -h 127.0.0.1 -U postgres -d lps_db -c "TRUNCATE job;"
|
|
#
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")" # lps/
|
|
|
|
VENV=".venv"
|
|
PY="$VENV/bin/python"
|
|
LOCUST="$VENV/bin/locust"
|
|
HOST="http://localhost:9600"
|
|
PORT=9600
|
|
WEBUI_PORT=8089
|
|
|
|
# 1) venv + locust 보장
|
|
if [[ ! -d "$VENV" ]]; then
|
|
echo "[setup] venv 생성 + 의존성 설치..."
|
|
python3 -m venv "$VENV"
|
|
"$PY" -m pip install -q --upgrade pip
|
|
"$PY" -m pip install -q -r requirements.txt
|
|
fi
|
|
if [[ ! -x "$LOCUST" ]]; then
|
|
echo "[setup] locust 설치..."; "$PY" -m pip install -q locust
|
|
fi
|
|
|
|
# 2) 워커가 떠 있으면 경고(부하 중 실제 크롤=비용)
|
|
if pgrep -f worker_main.py >/dev/null 2>&1; then
|
|
echo "[warn] 워커(worker_main.py)가 실행 중입니다 — 부하 중 실제 크롤 비용(프록시/AI)이 발생합니다."
|
|
read -rp " 워커를 종료할까요? [Y/n]: " k
|
|
[[ "${k:-Y}" =~ ^[Nn] ]] || { pkill -f worker_main.py || true; sleep 1; echo " 워커 종료"; }
|
|
fi
|
|
|
|
# 3) API 기동 확인 — 없으면 띄울지 물어본다
|
|
API_STARTED=""
|
|
if curl -s "$HOST/healthz" >/dev/null 2>&1; then
|
|
echo "[info] API 서버 감지됨 ($HOST)"
|
|
else
|
|
echo "[info] API 서버($HOST)가 응답하지 않습니다."
|
|
read -rp " 이 스크립트가 API 를 띄울까요? [Y/n]: " s
|
|
if [[ ! "${s:-Y}" =~ ^[Nn] ]]; then
|
|
read -rp " 멀티코어 PROCESS_COUNT [1] (풀은 자동 산정): " PC; PC="${PC:-1}"
|
|
echo " [run] web_main.py (PROCESS_COUNT=$PC) 백그라운드 기동..."
|
|
PROCESS_COUNT="$PC" APP_ENV=local "$PY" web_main.py > /tmp/lps_api_loadtest.log 2>&1 &
|
|
API_STARTED=$!
|
|
for _ in $(seq 1 20); do curl -s "$HOST/healthz" >/dev/null 2>&1 && break; sleep 1; done
|
|
if curl -s "$HOST/healthz" >/dev/null 2>&1; then
|
|
echo " API 기동 완료 (로그: /tmp/lps_api_loadtest.log)"
|
|
else
|
|
echo " [error] API 기동 실패 — /tmp/lps_api_loadtest.log 확인"; kill "$API_STARTED" 2>/dev/null || true; exit 1
|
|
fi
|
|
else
|
|
echo " [안내] 먼저 다른 터미널에서 ./run_local_server.sh 로 API 를 띄우세요."; exit 1
|
|
fi
|
|
fi
|
|
|
|
# 4) 부하 생성기 멀티프로세스(locust 자체가 병목되지 않게). 코어 많으면 늘린다.
|
|
CORES=$("$PY" -c "import os;print(os.cpu_count())")
|
|
read -rp "부하 생성기 프로세스 수 --processes [4] (CPU=$CORES): " LP; LP="${LP:-4}"
|
|
|
|
# API 를 이 스크립트가 띄웠으면 종료 시 함께 내린다
|
|
cleanup() { [[ -n "$API_STARTED" ]] && { echo ""; echo "[info] 스크립트가 띄운 API 종료"; kill "$API_STARTED" 2>/dev/null || true; }; }
|
|
trap cleanup EXIT
|
|
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════"
|
|
echo " Locust 웹 UI: http://localhost:$WEBUI_PORT"
|
|
echo " 대상 API : $HOST"
|
|
echo " → 브라우저에서 users/spawn rate 입력 후 START"
|
|
echo " 중단: Ctrl+C · 끝나면 쌓인 잡 정리:"
|
|
echo " psql -h 127.0.0.1 -U postgres -d lps_db -c 'TRUNCATE job;'"
|
|
echo "════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
# API 를 이 스크립트가 띄웠으면 exec 하지 않는다(종료 시 trap 으로 API 를 함께 내리기 위해).
|
|
if [[ -n "$API_STARTED" ]]; then
|
|
"$LOCUST" -f loadtest/locustfile.py --host "$HOST" --web-port "$WEBUI_PORT" --processes "$LP"
|
|
else
|
|
exec "$LOCUST" -f loadtest/locustfile.py --host "$HOST" --web-port "$WEBUI_PORT" --processes "$LP"
|
|
fi
|