마지막 업데이트 2026-09-17
quarantined; reconnecting),
규모를 10배 이상 잘못 읽게 하는 수치 1개(경고 712건),
근거 없이 단정하게 되는 결론 1개(CPU 독식)를 구분하면,
좀비의 확정된 해악은 워커 슬롯 점유 하나로 좁혀진다.
quarantined; reconnecting이 찍혔으니 세션이 고장났다”오해 20분마다 이 경고가 9번 찍혔다 → 세션이 망가진 채 job만 살아남았다.
실제 OpenAI Realtime 커넥션을 20분마다 재활용하는 정상 동작이다. 정상 수업 job도 20분을 넘기면 똑같이 찍는다.
vendor/livekit-plugins-openai/.../realtime/utils.py:62 — DEFAULT_MAX_SESSION_DURATION = 20 * 60apps/livekit-agent/agent.py:1355 — RealtimeModel(**realtime_model_kwargs)에 max_session_duration 미지정 → 기본 20분 적용realtime_model.py:1426 — 20분 타이머 만료 시 _run_ws 종료realtime_model.py:1175 — 그 finally에서 _quarantine_audio_commit_correlation() 호출 → realtime_model.py:2118의 WARNrealtime_model.py:1168-1170 — 곧바로 새 WS를 열고 _reconnect()로 chat_ctx 복원오해 712건이 곧 부하량이고, 최대 161.8s는 한 번의 추론에 걸린 시간이다.
실제 712는 추론 1회가 200ms를 넘겨 경고가 찍힌 횟수이고, 161.8s는 그 시점의 누적 밀림이다.
| 항목 | 값 | 근거 |
|---|---|---|
| 추론 창 1개 | 512샘플 / 16kHz = 32ms | Silero 표준값 (네이티브 상수) |
| 경고 임계 | 200ms | inference/vad.py:34 |
| 관측 구간 | 16:00:41~18:12:31 = 7,910초 | CloudWatch 집계 |
| 추론 호출 추정 | 약 247,000회 | 7,910 ÷ 0.032 |
| 그중 느렸던 것 | 712회 = 0.29% | — |
누적 밀림은 inference/vad.py:359-364에서 창마다 max(0, 누적 + 추론시간 − 창길이)로 더해지고, 따라잡을 때만 줄어든다. 값이 크다는 것은 “오래 밀린 상태가 유지됐다”는 뜻이지 “한 번이 오래 걸렸다”가 아니다.
오해 좀비가 한 코어를 100% 물고 있었고, 그래서 옆 job이 굶었다.
실제 실측이 이를 지지하지 않는다. 분당 지연 발생률은 좀비 5.4건/분 vs 피해 job 중앙값 51.9건/분으로 피해 job이 10배 더 밀렸고, 17:20까지는 같은 “동시 2개” 조건에서 정상이었다.
확정된 좀비의 기여는 슬롯 1칸을 3시간 점유해 모든 실수업을 ‘두 번째 동시 job’으로 만든 것까지다. 17:32경 임계를 넘긴 별도 요인은 여전히 미확정이며, 확정에는 해당 태스크의 CPU·메모리 그래프가 필요하다.
apps/livekit-agent/agent.py:355-373의 _ppi_agent_load가
active_jobs / MAX_JOBS_PER_WORKER만 반환한다(기본 2, agent.py:348). CPU 실측은 들어가지 않으므로
포화된 태스크도 load 0.495로 “여유 있음”을 광고한다. 워커 상태는 0.5초마다 재계산·신고된다(vendor/livekit-agents/.../worker.py:804).
반대 방향의 사고도 같은 원인에서 나온다 — 좀비 2개가 한 태스크의 슬롯 2/2를 채우면 load = 0.99 ≥ threshold가 되어 그 워커가 통째로 배정 대상에서 빠진다(2026-09-16 관측, 7시간 신규 job 0건).