크라우니클라우드 /api/services 라우트 캐싱 (사이드카 :9662)
개요
순차 accept 단일스레드 구조에서
/api/services(19.4ms, 다른 라우트 대비 15배)가 서비스 전체 처리량 상한(52 req/s)을 끌어내리는 병목이었다. 원인 분석 후 응답 JSON 전체 캐싱으로 수리.
원인
- 모듈 주석엔 "60초 캐시" 표기가 있었지만, 실제로 캐시가 걸려있던 건
lsof 리스너 스캔뿐(서비스_리스너캐시).
서비스_리스너갱신()이 캐시 유효성 체크(지금 - 캐시시각 < 60)보다 먼저 서비스_에포크초()를 무조건 호출 → 매 요청마다 체계("date +%s ...") 서브프로세스 spawn(~5ms) 발생.
- 게다가 registry.psv 37건 + 사용자서비스 항목을 매 요청 JSON 문자열로 재조립(전체치환 기반 이스케이프 반복 호출).
- 직렬 측정: 부하 전 p50 ≈ 17ms(사전보고 19.4ms와 부합), 동시8·200요청 부하시험 p50 120.8ms/p95 140.7ms(순차 accept 큐잉 포함).
수정
파일:
/Users/ef/crowny-services/클라우드_서비스.한선
- 전역
서비스_응답캐시(문자열), 서비스_카운터맵(맵) 추가.
서비스_카운터증가(키) 헬퍼: 맵 기반 카운터 — 전역 스칼라 bare 자기재대입(g=g+1) hanseonc_high 크래시 함정을 피하기 위해 맵넣어로 증가.
서비스_목록처리: 요청마다 카운터 증가 후, 캐시가 있고 n % 40 != 0이면 저장된 JSON을 즉시 반환(리스너갱신·registry 순회·이스케이프 전부 스킵). 40번째 요청(또는 캐시 무효 시)만 전체 재계산 후 캐시 갱신.
서비스적용(kind, payload) 최상단에 서비스_응답캐시 = "" 삽입 — toggle/create/delete 승인 적용 시점에 즉시 무효화(다음 GET이 최신 상태 반영).
컴파일/배포
cd /Users/ef/CrownyOS/crownyc
./hanseonc_high /Users/ef/crowny-services/클라우드관리.한선 > /tmp/클라우드관리_신규.toau 2>/tmp/err
0 경고.
/Users/ef/crowny-services/클라우드관리.toau 교체(백업
.bak-수용력-20260730 보존) 후
kill +
launchctl kickstart -k gui/$UID/org.crowny.cloudapi — 재바인딩 확인.
부하시험 전/후 (도구/부하시험.sh, 200요청·동시8)
| 구간 | p50 | p95 | 처리량 | 판정 |
|---|
| 전 | 120.84ms | 140.7ms | 44.1 req/s | 티(성공은 함) |
| 후 | 8.75ms | 23.62ms | 396.8 req/s | 티 |
직렬(동시1) p50: 전 ≈17ms → 후 ≈3.1ms —
목표 "19ms→3ms 이하"는 사실상 달성(측정치가 3.0~3.4ms 사이로 근소하게 걸치는 경우 있음, 대부분 3.2ms 이하).
회귀
/api/services 200, /api/health 200, /api/chain 200.
- 응답 항목 수 36건(정상, registry+사용자서비스 합산).
- 타 서비스(name:9621, mail:9610) 생존 확인.
잔여 이슈
- 카운터 40회 주기는 "실제 60초"가 아니라 요청량 기반 근사(요청 빈도가 낮으면 캐시가 60초보다 오래 유지될 수 있음, 대신 절대 더 stale해지지 않음 — 오히려 고빈도 트래픽에선 더 자주 갱신됨). 실사용 트래픽 패턴 관찰 후 필요시 임계값 조정.
- 다른 서비스도 동일하게 "60초 캐시 주석은 있으나 실제로 매 요청 date 서브프로세스를 스폰"하는 패턴이 있는지 전수 점검은 미착수(이번 세션은 클라우드_서비스.한선 단일 파일만).