서비스 디스커버리는 동적 환경에서 서비스 인스턴스의 네트워크 위치를 등록, 제거, 조회하는 메커니즘이다.
·수정 2026.04.24·수정 3회
요약
- 서비스 디스커버리는 동적 환경에서 서비스 인스턴스의 네트워크 위치를 등록/제거/조회하는 메커니즘
- 클라이언트 사이드/서버 사이드가 존재함
본문
해결하려는 문제
- 전통적 환경에서는 서비스 주소가 설정 파일이나 DNS에 고정되어 있었음
- 컨테이너/오토 스케일링 환경에서는 인스턴스가 수초 내에 생성/소멸되므로 정적 설정이 불가능함
내부 동작
- 레지스트리는 본질적으로 분산 key-value 저장소
- 서비스명:
[{instanceId, ip:port, metadata, status}]방식으로 저장됨 등록 방식
- self-registration: 서비스 인스턴스가 직접 레지스트리에 등록/해제, 서비스 코드에 레지스트리 클라이언트를 넣어야 하므로 언어*프레임워크 마다 구현이 필요함
- Third-party registration: 별도 프로세스(registrar)가 배포 환경을 감시하다가 새 인스턴스를 발경하면 등록하는 방식(k8s) 방식
- 서비스명:
Health Check 메커니즘
- TTL + heartbeat: 인스턴스가 주기적으로 heartbeat를 보내고, 일정 시간 안 오면 레지스트리가 자동 제거 ex) Eureka
- Active Health Check: 레지스트리가 능동적으로 인스턴스에 헬스체크를 보낸다. ex) Consul
디스커버리 메커니즘
- 클라이언트 사이드 디스커버리
- 서비스 A가 레지스트리에서 B의 인스턴스 목록을 받은 뒤 A 내부에서 로드밸런싱 알고리즘을 돌려 하나를 선택 ex) Netflix Ribbon
- 문제
- 모든 서비스에 디스커버리 + 로드 밸런싱 라이브러리가 돌아감
- 레지스트리 조회 결과를 로컬 캐싱하는데, 캐시가 stale해지면 죽은 인스턴스에 요청 보낼 수 있음
- 서버 사이드 디스커버리
- A가 로드 밸런서에 요청하면, 로드 밸런서가 레지스트리가 조회해서 라우팅함
- AWS ECS, ALB, K8s Service + kube proxy가 이 패턴
- 장점: 서비스 코드가 완전히 무관해짐
- 단점: 로드 밸런스 추가 홉, L7 수준의 세밀한 라우팅이 필요함
- A가 로드 밸런서에 요청하면, 로드 밸런서가 레지스트리가 조회해서 라우팅함
DNS 기반의 디스커버리를 쓰지 않는 이유
- DNS 캐싱 때문에 TTL 만료 전까지 죽은 인스턴스 주소가 남아 있을 수 있음
- TTL을 극단적으로 낮추면 해결되지만 DNS 서버에 부하