feat(backend): s3·aiServer 헬스 indicator + 컨테이너 healthcheck 를 readiness 로 - #184
Merged
Conversation
…ness 로 #183 에서 남겨둔 부분. `/api/system/health` 의 종합 status 가 s3·aiServer 미구현 때문에 UNKNOWN 으로 고정돼 있어 엔드포인트를 쓸 수 없었다. ## indicator 두 개 - `S3HealthIndicator` — `headBucket` 으로 엔드포인트·자격증명·버킷을 한 번에 확인. 스토리지가 죽으면 이력서 업로드·음성 답변·TTS 재생이 전부 실패한다. `ObjectStorageClient.verifyAvailable()` 을 추가했다(get/put 은 대상 키가 필요해서 헬스체크에 쓸 수 없다). - `AiServerHealthIndicator` — **작업 큐의 컨슈머 수**로 판단한다. Core 는 AI 를 HTTP 로 호출하지 않으므로(아키텍처 §4.1: RabbitMQ 전용) 헬스체크 하나 때문에 Core→AI HTTP 의존을 새로 만들지 않았다. 컨슈머 수가 오히려 정확한 신호다 — 프로세스 생존보다 **큐를 실제로 구독 중인가**가 중요하고, 컨슈머 0 이면 질문 생성·꼬리질문·피드백이 쌓이기만 한다. 브로커 자체가 죽은 경우는 UNKNOWN 으로 둔다(그건 rabbitmq 컴포넌트가 알려주므로 DOWN 을 겹쳐 내면 "AI 가 죽었다" 로 오독된다). 빈 이름이 곧 Actuator 키가 되도록 맞췄다(`s3HealthIndicator`→`s3`) — #183 과 같은 함정. ## 컨테이너 healthcheck 를 종합 → readiness 로 indicator 를 추가하면 종합(`/actuator/health`)에 s3·aiServer 가 들어가는데, 컨테이너 healthcheck 가 그 종합을 보고 있었다. 그대로 두면 **AI 가 죽었다고 백엔드 컨테이너가 unhealthy 가 되어** 정작 멀쩡한 로그인·히스토리까지 rotation 에서 빠진다. healthcheck 를 `/actuator/health/readiness` 로 바꾸고 readiness 그룹을 `readinessState + db + rabbit` 으로 **명시**했다. 그냥 liveness 로 바꾸면 DB 장애도 배포 게이트를 통과해 버리므로, 백엔드가 자기 일을 하려면 반드시 필요한 것만 남겼다. 그룹 멤버십 검증은 기본값(엄격)을 유지한다 — 이름을 틀리면 부팅이 실패해 배포에서 잡힌다. 조용히 UNKNOWN 이 되는 것보다 낫다(#183 이 정확히 그 실패였다). 테스트 프로파일은 DataSource 를 제외하므로 거기서만 그룹을 축소했다. ## 테스트 - `AiServerHealthIndicatorTest` (4) — 컨슈머 있음 UP, 0이면 DOWN(쌓인 메시지 수 포함), 큐 없음 DOWN, 브로커 불가 UNKNOWN - `S3HealthIndicatorTest` (2) — 도달 가능 UP, 실패 시 DOWN + 사유
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
변경 사항
#183 에서 남겨둔 부분.
/api/system/health의 종합 status 가 s3·aiServer 미구현 탓에 UNKNOWN 으로 고정돼 있어 엔드포인트를 쓸 수 없었다.indicator 두 개
S3HealthIndicator—headBucket으로 엔드포인트·자격증명·버킷을 한 번에 확인한다. 스토리지가 죽으면 이력서 업로드·음성 답변·TTS 재생이 전부 실패한다.ObjectStorageClient.verifyAvailable()을 추가했다 —get/put은 대상 키가 필요해서 헬스체크에 쓸 수 없다.AiServerHealthIndicator— 작업 큐의 컨슈머 수로 판단한다.HTTP 로 AI 서버를 찌르지 않은 이유:
브로커 자체가 죽은 경우는 DOWN 이 아니라 UNKNOWN 으로 둔다. rabbitmq 컴포넌트가 이미 알려주는 사실이라, 여기서 DOWN 을 겹쳐 내면 "AI 가 죽었다" 로 오독된다.
빈 이름이 곧 Actuator 키가 되도록 맞췄다(
s3HealthIndicator→s3,aiServerHealthIndicator→aiServer) — #183 과 정확히 같은 함정이라SystemHealthService는 한 줄도 안 고쳤다.컨테이너 healthcheck 를 종합 → readiness 로
이게 이 PR 의 진짜 판단이다. indicator 를 추가하면 종합(
/actuator/health)에 s3·aiServer 가 들어가는데, 컨테이너 healthcheck 가 그 종합을 보고 있었다. 그대로 두면 AI 가 죽었다는 이유로 백엔드 컨테이너가 unhealthy 가 되어 정작 멀쩡한 로그인·히스토리·이력서 업로드까지 rotation 에서 빠진다. 상황을 더 나쁘게 만드는 쪽이다.healthcheck 를
/actuator/health/readiness로 바꾸고 readiness 그룹을 명시했다:그냥 liveness 로 바꾸지 않은 이유: liveness 기본 그룹은
livenessState뿐이라 DB 장애도 배포 게이트를 통과해 버린다. 지금 게이트가 잡아주는 안전성을 잃는다. 백엔드가 자기 일을 하려면 반드시 필요한 것(DB·RabbitMQ)만 남겼다.그룹 멤버십 검증(
validate-group-membership)은 기본값(엄격)을 유지한다 — 이름을 틀리면 부팅이 실패해 배포에서 잡힌다. 조용히 UNKNOWN 이 되는 것보다 낫다. #183 이 정확히 그 실패였다. 테스트 프로파일은 DataSource 를 제외하므로 거기서만 그룹을 축소했다.결과
/api/system/health/api/system/ready테스트
AiServerHealthIndicatorTest(4) — 컨슈머 있음 UP, 0이면 DOWN(쌓인 메시지 수 포함), 큐 없음 DOWN, 브로커 불가 UNKNOWNS3HealthIndicatorTest(2) — 도달 가능 UP, 실패 시 DOWN + 사유backend
test통과(ArchUnit·컨텍스트 로딩 포함).영향 범위
리뷰어 체크포인트
ai.generate.questions큐 하나만 본다. 여러 큐를 보거나 최소 컨슈머 수를 요구하는 게 나을지