Skip to content

feat: 브레이커 open 웹훅 알림과 GET 한정 재시도를 붙인다 - #86

Merged
popeye0618 merged 1 commit into
feat/feign-circuit-breakerfrom
feat/feign-alert-retry
Aug 26, 2026
Merged

popeye0618 merged 1 commit into
feat/feign-circuit-breakerfrom
feat/feign-alert-retry

Conversation

@popeye0618

Copy link
Copy Markdown
Member

배경

Feign 안정화 Phase 3. #85(서킷브레이커) 위에 쌓인 브랜치다 — #85 머지 후 리뷰/머지하면 된다.

브레이커가 열리면 서비스는 스스로 버티지만(즉시 503), 사람이 모르면 브레이커는 장애를 견디는 장치가 아니라 숨기는 장치가 된다. open 알림을 붙이고, 함께 미뤄뒀던 GET 한정 재시도를 추가한다.

변경 내용

1. 브레이커 open/복구 웹훅 알림 (CircuitBreakerAlertNotifier)

  • Prometheus + Alertmanager가 아니라 발행 시점 직접 웹훅인 이유는 KafkaDltAlertNotifier와 같다 — 모니터링 스택(docker-compose.monitoring.yml)은 부하 테스트용으로 필요할 때만 띄우는 구성이라 상시 알림의 기반이 못 된다. {"content","text"} 겸용 키(Discord/Slack)도 같은 규칙.
  • 쿨다운(브레이커별 5분): 지속 장애 중 브레이커는 open → half-open → open을 10초마다 반복한다. 쿨다운 없으면 장애 5분에 알림 30건. 억제 횟수는 다음 알림에 합산 보고.
  • 복구 알림은 open 알림이 실제 나간 경우에만 한 번 — 억제된 open에 복구까지 짝지으면 도배가 두 배가 된다.
  • 전송은 별도 스레드: 상태 전이 이벤트는 그 전이를 일으킨 요청 스레드에서 동기 발화하므로, 웹훅 HTTP(최대 3s)가 사용자 응답을 붙잡으면 안 된다.
  • 웹훅 URL: CIRCUIT_BREAKER_ALERT_WEBHOOK_URL → 없으면 DLT_ALERT_WEBHOOK_URL → 그것도 없으면 로그만. 기존 배포 env 그대로 두면 DLT와 같은 채널로 바로 알림이 온다(추가 배포 설정 불필요).

2. GET 한정 1회 재시도 (InternalGetRetryer)

  • 기본 NEVER_RETRY를 대체. 전송 실패(RetryableException)에만 동작한다 — HTTP 응답을 받은 5xx는 재시도하지 않는다.
  • GET으로 제한하는 이유: 전송 실패는 서버가 처리를 했는지 알 수 없는 상태다. read-timeout이면 요청이 이미 도달해 처리됐을 수 있고, 그 상태에서 POST(아이템 차감, 방 생성)를 다시 보내면 중복 실행이 된다.
  • 대가: GET 최악 지연이 read-timeout 두 배(기본 3s → 6.1s). 지속 장애면 브레이커가 열려 무한 반복은 안 된다. 재시도 전체는 브레이커 안에서 한 번의 호출로 집계.

검증

  • FeignRetryTest — 응답 없는 소켓 서버를 상대로 실제 연결 횟수를 센다: GET은 연결 2회 후 실패, POST는 1회 후 즉시 실패. 서킷브레이커 경로(feign-resilience.yml 그대로 임포트)를 물고 돌므로 브레이커 안에서의 재시도 동작까지 확인.
  • CircuitBreakerAlertNotifierTest — 시계 주입으로 쿨다운 경계·억제 합산·복구 짝 규칙·웹훅 미설정 무동작을 결정적으로 검증 (KafkaDltAlertNotifierTest와 같은 방식).
  • 전 모듈 단위 테스트 통과. 기존 FeignCircuitBreakerTest도 재시도·알림 빈이 활성화된 채로 통과(타임아웃 재시도가 브레이커에 1건으로 집계되는 것 포함).

하위 호환성

  • API·이벤트 스키마 변경 없음. common-module 변경이라 전체 재배포 한 번으로 롤아웃.
  • notification/gateway는 com.comatching.common.config를 스캔하지 않아 영향 없음(각각 @import 선별 / 스캔 경로 제한 확인).
  • 알림은 env 미설정 시 로그만 남기므로 켜기 전에도 안전하다.

🤖 Generated with Claude Code

브레이커가 열리면 서비스는 스스로 버티지만(즉시 503), 사람이 모르면
브레이커는 장애를 견디는 장치가 아니라 숨기는 장치가 된다. DLT 알림과
같은 방침(상시 모니터링 스택이 없으므로 발행 시점 직접 웹훅)으로
open/복구를 알린다.

- open 알림은 브레이커별 쿨다운(5분)으로 도배를 막고 억제 횟수를 합산
  보고한다. 복구 알림은 open 알림이 실제 나간 경우에만 짝지어 한 번.
- 전송은 별도 스레드 - 상태 전이는 그 전이를 일으킨 요청 스레드에서
  동기 발화하므로 웹훅 HTTP 가 사용자 응답을 붙잡으면 안 된다.
- 웹훅 env 미설정이면 DLT 웹훅을 그대로 쓰고, 그것도 없으면 로그만.

재시도는 GET 한정 1회. 전송 실패(RetryableException)는 서버가 처리를
했는지 알 수 없는 상태라 비멱등 요청 재전송은 중복 실행이 된다.
재시도 전체는 브레이커 안에서 한 번의 호출로 집계된다.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@popeye0618
popeye0618 merged commit 2ba0533 into feat/feign-circuit-breaker Aug 26, 2026
1 check passed
@popeye0618
popeye0618 deleted the feat/feign-alert-retry branch August 26, 2026 08:31
@claude

claude Bot commented Aug 26, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant