Service Registry

Service Registry는 마이크로서비스 환경에서 각 서비스 인스턴스의 네트워크 위치(IP 주소와 포트)를 저장하고 관리하는 중앙화된 데이터베이스이다.
이는 동적으로 변화하는 마이크로서비스 환경에서 서비스 디스커버리를 가능하게 하는 핵심 요소이다.

Service Registry는 MSA 환경에서 서비스 디스커버리를 가능하게 하는 핵심 컴포넌트이다. 이를 통해 동적이고 확장 가능한 마이크로서비스 아키텍처를 구현할 수 있다.

서비스 레지스트리의 중요성

MSA 환경에서는 서비스 인스턴스가 자동 확장, 장애 복구, 배포 등의 이유로 동적으로 생성되고 소멸되며, 이에 따라 네트워크 위치가 변경된다.
이러한 동적인 특성으로 인해, 서비스 레지스트리는 다음과 같은 역할을 수행한다:

  • 동적 스케일링 지원: 서비스 인스턴스의 추가 및 제거 시 자동으로 정보를 갱신하여, 클라이언트가 항상 최신 서비스 위치를 알 수 있도록 한다.
  • 장애 대응: 장애가 발생한 인스턴스를 목록에서 제거하여, 클라이언트가 비정상적인 인스턴스로의 요청을 방지한다.
  • 로드 밸런싱 지원: 현재 가용한 서비스 인스턴스 목록을 제공하여, 로드 밸런서나 클라이언트가 효율적으로 부하를 분산할 수 있도록 돕는다.

Service Registry의 주요 기능

  1. 서비스 등록: 각 마이크로서비스 인스턴스는 시작 시 자신의 정보(서비스 이름, IP 주소, 포트 등)를 Service Registry에 등록한다.
  2. 서비스 조회: 클라이언트나 다른 서비스들이 특정 서비스의 위치 정보를 요청할 때 이를 제공한다.
  3. 상태 모니터링: 등록된 서비스들의 상태를 주기적으로 확인하여 가용성을 관리한다.
  4. 동적 업데이트: 서비스 인스턴스가 추가되거나 제거될 때 자동으로 정보를 업데이트한다.

Service Registry의 구현 방식

  1. 중앙 집중식 데이터베이스: 모든 서비스 정보를 중앙에서 관리한다.
  2. 분산 시스템: 고가용성을 위해 여러 노드에 걸쳐 정보를 복제한다.
  3. API 제공: 서비스 등록, 조회, 삭제 등을 위한 REST API를 제공한다.

주요 Service Registry 도구

  1. Netflix Eureka: 클라이언트 사이드 서비스 디스커버리에 주로 사용되는 오픈소스 도구이다.
  2. Apache ZooKeeper: 분산 코디네이션 서비스로, 서비스 레지스트리 기능을 제공한다.
  3. Consul: HashiCorp에서 개발한 서비스 디스커버리 및 구성 도구이다.
  4. etcd: 분산 키-값 저장소로, 서비스 레지스트리로 활용될 수 있다.

Service Registry의 장점

  1. 동적 확장성: 서비스 인스턴스의 동적 추가 및 제거를 지원한다.
  2. 고가용성: 분산 시스템으로 구현되어 단일 실패 지점을 방지한다.
  3. 자동화: 서비스 등록 및 해제 과정을 자동화하여 운영 효율성을 높인다.
  4. 유연성: 클라우드 환경에서 IP 주소가 동적으로 변경되는 상황에 대응할 수 있다.

주의사항

  1. 데이터 일관성: 분산 환경에서 데이터 일관성을 유지하는 것이 중요하다.
  2. 보안: 서비스 정보의 중앙 저장소이므로 보안에 각별한 주의가 필요하다.
  3. 성능: 많은 요청을 처리해야 하므로 성능 최적화가 중요하다.

구현 예시

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 서비스 레지스트리 구현
class ServiceRegistry {
    constructor() {
        // 서비스 정보 저장소
        this.services = new Map();
        
        // 이벤트 구독자 관리
        this.subscribers = new Map();
        
        // 서비스 상태 정보
        this.healthStatus = new Map();
        
        // 레지스트리 설정
        this.config = {
            cleanupInterval: 30000,  // 30초마다 정리
            healthCheckInterval: 10000  // 10초마다 헬스체크
        };

        // 주기적인 정리 작업 시작
        this.startCleanupTask();
        this.startHealthCheck();
    }

    // 서비스 등록
    async registerService(serviceInfo) {
        const serviceId = this.generateServiceId(serviceInfo);
        
        const registration = {
            id: serviceId,
            name: serviceInfo.name,
            host: serviceInfo.host,
            port: serviceInfo.port,
            metadata: serviceInfo.metadata || {},
            registrationTime: Date.now(),
            lastHeartbeat: Date.now()
        };

        // 서비스 정보 저장
        this.services.set(serviceId, registration);
        
        // 이벤트 발행
        this.notifySubscribers('SERVICE_REGISTERED', registration);
        
        return serviceId;
    }

    // 서비스 조회
    async getServiceInstances(serviceName) {
        const instances = Array.from(this.services.values())
            .filter(service => 
                service.name === serviceName && 
                this.isHealthy(service.id)
            );

        if (instances.length === 0) {
            throw new Error(`No healthy instances found for service: ${serviceName}`);
        }

        return instances;
    }
}

참고 및 출처