J4025 Celeron 2C/2.0GHz에서 oversaturation을 일으키던 5개 패턴 해소. 1) 09:00 cron 스태거링 — agent-office insta_trends 09:00 / lotto 09:05 / youtube 09:10, realestate-lab collect 09:15. 동시 실행 4개가 직렬 분산되어 1분 단위로 분산됨. 2) lotto Monte Carlo 08:05 → 08:30 — stock 08:00 cron과 25분 분리. 3) insta-lab card_renderer.render_slate를 asyncio.Semaphore(1)로 감쌈. 동시 슬레이트 렌더 요청이 와도 Chromium 인스턴스 1개만 직렬 launch. 4) docker-compose healthcheck interval 30s → 60s (9 백엔드 + frontend 총 10개). 30초마다 동시 healthcheck로 인한 CPU 잡음 절반으로. 5) 9개 백엔드 Dockerfile CMD에 --workers 1 명시. 기본값 의존 제거. CHECK_POINT.md 갱신 — 즉시 5건 체크 + 변경 이력 한 줄. 적용 효과 검증: NAS 재기동 후 `docker stats` 비교. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.4 KiB
6.4 KiB
web-backend CHECK_POINT
NAS Docker 11 컨테이너(9 백엔드 + frontend + deployer). Synology Celeron J4025 (2C 2.0GHz) 18GB. 2026-05-18 작성 — uvicorn CPU 폭주 진단 결과 정리.
🔴 즉시 (오늘, 총 1시간 5분)
1. 09:00 cron 5분 스태거링 ⭐ 가장 큰 효과
파일: agent-office/app/scheduler.py:72-76
# 변경 전 — 09:00 동시 실행 (CPU 폭주 원인 #1)
scheduler.add_job(_run_insta_trends_collect, "cron", hour=9, minute=0)
scheduler.add_job(_run_lotto_schedule, "cron", day_of_week="mon", hour=9, minute=0)
scheduler.add_job(_run_youtube_research, "cron", hour=9, minute=0)
# 변경 후 — 5분 스태거링
scheduler.add_job(_run_insta_trends_collect, "cron", hour=9, minute=0, id="insta_trends")
scheduler.add_job(_run_lotto_schedule, "cron", day_of_week="mon", hour=9, minute=5, id="lotto_curate")
scheduler.add_job(_run_youtube_research, "cron", hour=9, minute=10, id="youtube_research")
파일: realestate-lab/app/main.py:51
# 변경 전
scheduler.add_job(scheduled_collect, "cron", hour=9, minute=0, id="collect")
# 변경 후
scheduler.add_job(scheduled_collect, "cron", hour=9, minute=15, id="collect")
- agent-office scheduler.py 수정 (2026-05-18)
- realestate-lab main.py 수정 (2026-05-18)
- git commit + push (Gitea Webhook 자동 빌드)
2. insta-lab Playwright Semaphore(1) ⭐
파일: insta-lab/app/main.py (모듈 레벨 추가)
import asyncio
# 모듈 레벨에 한 번만 선언
RENDER_SEMAPHORE = asyncio.Semaphore(1) # Chromium 동시 실행 1개로 제한
# 카드 렌더 백그라운드 함수에 감싸기
async def _bg_render(task_id: str, slate_id: int):
async with RENDER_SEMAPHORE:
await card_renderer.render_slate(slate_id, ...)
- card_renderer.render_slate를 Semaphore(1)로 감쌈 (2026-05-18, lazy init)
- 동시 2개 요청 테스트 (curl 동시 2회 → 순차 처리되는지 확인)
3. healthcheck interval 60s
파일: docker-compose.yml (모든 9 컨테이너)
# 변경 전
healthcheck:
interval: 30s
# 변경 후
healthcheck:
interval: 60s
- docker-compose.yml 10개 healthcheck 일괄 변경 (9 백엔드 + frontend, 2026-05-18)
docker compose up -d재기동docker stats로 CPU 5% 정도 감소 확인
4. uvicorn --workers 1 명시
모든 Dockerfile CMD:
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
영향 9 파일 (모두 2026-05-18 적용):
- lotto/Dockerfile
- stock/Dockerfile
- music-lab/Dockerfile
- insta-lab/Dockerfile
- realestate-lab/Dockerfile
- agent-office/Dockerfile
- personal/Dockerfile
- packs-lab/Dockerfile
- travel-proxy/Dockerfile
→ docker compose build --no-cache 후 재기동.
5. lotto Monte Carlo 08:05 → 08:30
파일: lotto/app/main.py:86
# 변경 전 — stock 08:00과 5분 차이로 겹침
scheduler.add_job(_run_simulation_job, "cron", hour="0,4,8,12,16,20", minute=5)
# 변경 후 — 25분 분리
scheduler.add_job(_run_simulation_job, "cron", hour="0,4,8,12,16,20", minute=30)
- lotto/app/main.py 수정 (2026-05-18)
🟡 중기 (1~2주)
6. Chromium Browser Pool 재설계 (insta-lab)
- 매번 launch X → 1개 인스턴스 재사용
- 카드 10장 렌더 시간 30% 단축 기대
insta-lab/app/browser_pool.py신규 모듈- card_renderer에서 풀 사용
7. stock 뉴스 스크랩 비동기화
- 파일:
stock/app/main.py:104-149 run_scraping_job()동기 → BackgroundTask 또는 asyncio- 08:00 APScheduler 블로킹 해소
- async/await 변환
8. realestate 수집 병렬화
- 파일:
realestate-lab/app/main.py:28-37 collect_all()+delete_old()병렬 →asyncio.gather- 매칭은 순차 유지 (DB 일관성)
- async 함수 변환 + gather 적용
9. lotto Monte Carlo 시뮬레이션 빈도 검토
- 현재 6회/일 (00·04·08·12·16·20)
- 실제 필요 빈도 박재오 결정 — 3회/일(아침·점심·저녁)로 줄이면 CPU 50% 감소
- 박재오 의사결정 후 cron 변경
🟢 장기 (1개월+)
10. 무거운 작업 Windows AI 서버로 이전
- 현재 stock Ollama qwen3:14b → NAS 로컬 호출 가능성 (확인 필요)
- 모든 LLM 호출을 Windows AI 192.168.45.59로 통일
- NAS CPU ~20% 감소 기대
11. 컨테이너 리소스 제한
services:
insta-lab:
deploy:
resources:
limits:
cpus: "0.5"
memory: "512M"
- insta-lab·music-lab·stock 등 무거운 컨테이너부터 적용
- 효과: OOM killer로부터 다른 컨테이너 보호
12. NAS 업그레이드 검토
- 현재: Celeron J4025 (2C 2.0GHz)
- 대안: Ryzen N5105 (4C 2.0GHz) NAS — 4코어로 병렬성 2배
- 박재오 자금·우선순위 결정
✅ 최근 완료 (참고)
- 2026-05-15: insta-lab 신설 (포트 18700, Jinja2 + Playwright + Claude Sonnet)
- 2026-05-16: insta-lab Playwright 1080×1350 PNG 렌더 완성
- 2026-05-17: agent-office random idle 제거, ADMIN_API_KEY 강화 (stock)
- 2026-05-17: insta-lab minimal theme + design_importer 추가
- 2026-05-17: blog-lab 트랙 완전 폐기 (docker-compose에 없음, 위키 정정 완료)
- 2026-05-18: 🔴 즉시 5건 일괄 적용 — 09:00 cron 스태거링(insta/lotto/youtube/realestate), lotto Monte Carlo 08:30, insta-lab Semaphore(1), healthcheck 60s, uvicorn --workers 1 명시 (사용자 push + NAS deployer 재기동 대기)
🔧 진단 커맨드 (NAS bash)
# 실시간 CPU 사용 (상위 15)
top -b -n 1 | head -25
# 프로세스별 CPU 정렬
ps aux --sort=-%cpu | head -15
# uvicorn·chromium·python 프로세스만
ps aux | grep -E "uvicorn|chromium|python" | grep -v grep
# 스케줄러 실행 로그 (최근 50)
docker logs agent-office 2>&1 | grep -E "APScheduler|executing" | tail -50
# insta-lab Chromium 프로세스 개수
docker exec insta-lab ps aux | grep chromium | wc -l
# 컨테이너별 CPU/메모리 실시간
docker stats --no-stream
📚 참고
- 진단 풀 보고서:
C:\Users\jaeoh\Documents\Obsidian Vault\raw\2026-05-18-NAS-uvicorn-CPU-진단-개선안.md - 위키 페이지: 사업-개인-웹-플랫폼 (CPU 부하 진단 섹션 + 컨테이너 표)
- docker-compose.yml: 본 디렉토리 루트
변경 이력
- 2026-05-18: 페이지 신설. 즉시 5건 + 중기 4건 + 장기 3건. 진단 커맨드.