MSA(Microservices Architecture)나 클라우드 환경에서는 수많은 서비스들이 컨테이너나 VM 위에서 동적으로 실행된다.
이 때, 서비스의 위치(IP, Port) 가 고정적이지 않고, 실행될 때마다 달라질 수 있는데,
클라이언트(또는 다른 서비스)가 특정 서비스를 호출하려면 이 동적으로 변하는 주소를 알아야 한다.
이 문제를 해결하는 게 서비스 디스커버리이다.
쉽게 말해, “서비스가 어디에 있는지 찾아주는 주소록 시스템” 이라고 이해하면 된다
Spring Cloud에서 가장 대표적으로 쓰이는 서비스 디스커버리 구현체 중 하나.
(Netflix에서 만든 서비스 디스커버리 서버)
구성 요소는 크게 두 가지이다:
1. Eureka Server: 모든 서비스의 위치 정보를 저장하는 중앙 레지스트리 (등록소)
2. Eureka Client: 자신을 서버에 등록하고, 다른 서비스의 위치를 조회하는 클라이언트 모듈
어제와 오늘 공부한 것을 통합해서 동작 흐름을 정리해보았다.
Eureka (서비스 디스커버리)
→ 서비스들의 주소(IP/Port)를 등록·조회하는 중앙 서버
Feign Client (Declarative REST Client)
→ @FeignClient 인터페이스만 선언하면, 실제 HTTP 요청을 대신 보내주는 클라이언트
(즉, RestTemplate의 선언형/자동화 버전이라고 생각하면 됨)
Ribbon (로드밸런서)
→ Eureka에서 가져온 여러 인스턴스 주소 중에서 어느 서버에 보낼지 결정하는 클라이언트 사이드 로드밸런서
(Spring Cloud 최신 버전에서는 Ribbon 대신 Spring Cloud LoadBalancer 사용)
Resilience4j (서킷 브레이커 라이브러리)
→ 호출 실패나 지연이 발생했을 때 시스템을 보호하는 기능 제공
(Circuit Breaker, Retry, Rate Limiter, Bulkhead 등의 기능 제공)
Order-Service
↓ (Feign 호출)
Feign Client
↓ (Eureka 조회)
Eureka Server → 서비스 인스턴스 목록 반환
↓ (Ribbon 선택)
Ribbon (LoadBalancer)
↓ (실제 HTTP 전송)
User-Service (10.0.0.x:port)
↑ (응답)
Resilience4j (실패 시 재시도, Circuit Breaker, Fallback)
↓
Order-Service
1. Feign Client 호출
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/{id}")
UserResponse getUser(@PathVariable Long id);
}
OrderService 코드에서 개발자가 userClient.getUser(1L) 호출하면, Feign이 자동으로 HTTP 요청을 준비한다2. 서비스 주소 조회 (Eureka)
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/{id}")
UserResponse getUser(@PathVariable Long id);
}
3. 로드 밸런싱 (Ribbon)
4. 실제 HTTP 요청 전송
5. Resilience4j 적용 (장애 대응)
만약 10.0.0.1:8081이 죽어 있다면?
결과적으로 전체 서비스 장애 확산을 방지
Eureka와 Ribbon의 역할이 비슷해보여 헷갈려서 다시 짚고 넘어가자면, 둘은 관심사가 다르다.
Eureka의 역할 (서비스 디스커버리):
서비스 주소록 = "어디에 있나?"
Ribbon의 역할 (로드 밸런서):
부하 분산 = "누구한테 보낼까?"
예 1)
Eureka: “user-service가 지금 2개 살아 있어 → (10.0.0.1:8081, 10.0.0.2:8082)”
Ribbon: “좋아, 그럼 이번 요청은 10.0.0.2:8082로 보낼게”
예 2)
Eureka = 전화번호부
“피자가게 전화번호 알려줘” → 여러 개 반환
Ribbon = 내가 전화를 걸 때 누구한테 먼저 걸지 정하는 사람
이번에는 1번 지점 전화 걸고, 다음에는 2번 지점 전화 걸고
쉽게 말해,
Eureka = 주소 제공자
Ribbon = 주소 선택자
➡️ Eureka가 ‘목록’을 주고 Ribbon이 ‘선택’을 한다
이렇게 이해하면 깔끔한 것 같다