DOCS/journey/research/260304_51124_먹통_48시간_코드차분_원인확정_리서치.md

5.2 KiB

51124 먹통: 48시간 코드 차분 기반 원인 확정 리서치

작성일: 2026-03-04
범위: rb8001, robeing-gateway, robeing-monitor, skill-email, skill-embedding, skill-rag-file 최근 48시간 커밋/디프
목표: 51124 CPU 폭주/먹통의 원인을 코드 근거로 확정하고, 재발 방지 해법을 운영 관점으로 고정


1. 결론(확정)

  • 24 서버 먹통의 직접 경로는 INTENT_ENGINE=graph + INTENT_USE_LANGGRAPH=true 활성 시 의도 분류 워크플로우 내부 재진입 구조다.
  • 재진입 지점은 IntentGraph.detect_with_workflow() → LangGraph classify_intent_node()IntentGraph.detect() 재호출로 확인된다.
  • 23 서버가 같은 증상을 재현하지 않은 이유는 임시복구 시 .env에서 INTENT_ENGINE=v1, INTENT_USE_LANGGRAPH=false로 강제 다운그레이드했기 때문이다.

2. 근거(코드/문서)

2.1 48시간 주요 변경

  • rb8001 3532600: docker-compose.yml 기본값이 INTENT_ENGINE=v1 -> graph로 변경됨.
  • rb8001 1f39d08: /api/message 응답 후 자기개선 아티팩트 DB 기록 경로 추가(부하 증가 요인).
  • robeing-gateway 5b97bea: 프록시가 method/body/content-type 전달하도록 변경(이전보다 실제 경로 실행률 상승).
  • robeing-monitor 1221596: /health 호환 엔드포인트 추가(먹통 직접 원인으로 보기 어려움).

2.2 재진입(재귀) 경로

  • rb8001/app/services/brain/intent_graph.py:39-41
    • INTENT_USE_LANGGRAPH=truedetect()detect_with_workflow()를 호출.
  • rb8001/app/services/brain/intent_graph.py:65
    • detect_with_workflow()가 LangGraph workflow ainvoke 실행.
  • rb8001/app/services/brain/intent_langgraph_workflow.py:49-60
    • classify_intent_node() 내부에서 새 IntentGraph 생성 후 intent_graph.detect(message, context) 재호출.
  • 위 3개가 결합되어, 워크플로우 내부 분류 노드가 다시 워크플로우 진입 경로를 호출하는 구조가 성립한다.

2.3 23/24 차이의 확정 근거

  • DOCS/journey/troubleshooting/260304_51123_임시복구_서비스연속성_조치내역.md:43-49
    • 51123 임시복구에서 INTENT_ENGINE=v1, INTENT_USE_LANGGRAPH=false 적용 기록이 명시됨.
  • rb8001/.env:185-188
    • 동일 임시복구 성능 오버라이드가 실제 파일에도 존재.
  • 따라서 같은 코드 베이스라도 23은 재진입 경로를 비활성화했고, 24는 기본 graph 경로를 타서 증상이 확대될 수 있다.

2.4 외부 근거(공식 문서)

3. 원인/비원인 구분

구분 항목 판정 이유
원인 의도 분류 워크플로우 재진입 구조 확정 코드 호출 체인이 직접 닫힌 루프를 형성
증폭 /api/message 자기개선 DB 기록 추가 확정 요청당 DB 작업/연결 증가
증폭 gateway 프록시 body/header 전달 확대 확정 기존 차단/오류 경로가 실제 실행으로 전환
비원인 robeing-monitor /health 추가 제외 라우트 1개 추가로 CPU 폭주 구조가 생기지 않음
비원인 RAM 부족 제외 기존 관측값 기준 swap/OOM 근거 없음

4. 해결책(정확/우선순위)

P0 즉시(운영 보호)

  1. 24 서버 배포 전 기본값을 재진입 없는 안전값으로 고정:
    • INTENT_ENGINE=v1
    • INTENT_USE_LANGGRAPH=false
  2. 적용 후 30분 관찰 기준:
    • 컨테이너 Restarting 0회
    • python main.py CPU 지속 고점 급등 재발 없음

P1 구조 수정(근본)

  1. IntentGraph.detect()에 워크플로우 내부 호출 구분 플래그를 추가해 재진입 차단.
  2. 또는 classify_intent_node()IntentGraph.detect()가 아닌 전통 분류 함수만 직접 호출하도록 분리.
  3. 회귀 테스트 추가:
    • "workflow classify node가 detect_with_workflow를 다시 호출하지 않는다" 단언 테스트.

P2 검증 고정(재발 방지)

  1. 배포 파이프라인에 스모크 테스트 추가:
    • INTENT_ENGINE=graph 상태에서 단일 메시지 처리 시 호출 깊이/시간 상한 검증.
  2. 런타임 가드:
    • 의도 분류 단계 실행 횟수 카운터를 요청 단위로 기록, 임계 초과 시 즉시 오류/중단.

5. 운영 판정 기준

  • 완료 판정은 "응답 속도"가 아니라 "먹통 재발 차단"이다.
  • 아래를 동시에 만족해야 완료:
    • restart loop 0회
    • 운영자가 전체 컨테이너 강제중지 없이 장애 제어 가능
    • 09:00~10:00 주요 스케줄 구간에서 CPU 급등/응답 중단 없음