[TIL] MSA, Eureka

Soeng_dev·2024년 11월 20일

:: MSA

하나의 애플리케이션을 여러 독립적인 서비스로 분리

• 장점

  • 개발, 배포, 유지보수 쉬움
  • 장애 전파 방지
  • 서비스마다 다른 기술스택 사용 가능

• 단점

  • 데이터일관성 유지 힘듬
  • 서비스간 통신 구축 필요
  • 응답시간 지연
    -> 서비스간 통신 필요, 한 기능에 필요한 통신횟수 증가
  • 각 서비스의 모니터링/로깅 개별관리 필요
    -> 운영비용 증가

:: Spring Cloud

MSA구축 위한 스프링 확장 기능

• 주요 기능

  • 서비스 등록 및 디스커버리: Eureka, Consul, Zookeeper
  • 로드 밸런싱: Ribbon, Spring Cloud LoadBalancer
  • 서킷 브레이커: Hystrix, Resilience4j
  • API 게이트웨이: Zuul, Spring Cloud Gateway
  • 구성 관리: Spring Cloud Config
  • 분산 추적: Spring Cloud Sleuth, Zipkin
  • 메시징: Spring Cloud Stream

• Config 방식

  • 중앙집중식 설정 관리: config서버 -> client서버 (서비스 서버)
  • config 변경시 재시작 없이 실시간 반영

:: Eureka

• Eureka 서버

서비스 인스턴스의 레지스트리 구성하는 중앙 서버

» 서버 설정

server:
  port: 8761

eureka:
  client:
    register-with-eureka: false  # 다른 Eureka 서버에 이 서버를 등록하지 않음
    fetch-registry: false  # 다른 Eureka 서버의 레지스트리를 가져오지 않음
  server:
    enable-self-preservation: false  # 자기 보호 모드 비활성화 

» 고가용성 구성

  • 여러 eureka 중앙 서버를 사용가능

  • 각 인스턴스는 서로를 피어로 등록하여 상호 백업

eureka:
  client:
    service-url:
      defaultZone: http://eureka-peer1:8761/eureka/,http://eureka-peer2:8761/eureka/

• Eureka 클라이언트

  • 각 서비스는 Eureka 서버에 자신을 등록
  • spring-cloud-starter-netflix-eureka-client 의존성 및
    설정파일에 애플리케이션 이름 설정하면 eureka 자동 등록

» 클라이언트 설정

spring-cloud-starter-netflix-eureka-client 의존성을 사용


spring:
  application:
    name: my-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/  # Eureka 서버 URL
    register-with-eureka: true  # Eureka 서버에 등록
    fetch-registry: true  # Eureka 서버로부터 레지스트리 정보 가져오기
  instance:
    hostname: localhost  # 클라이언트 호스트 이름
    prefer-ip-address: true  # IP 주소 사용 선호
    lease-renewal-interval-in-seconds: 30  # 리스 갱신 간격
    lease-expiration-duration-in-seconds: 90  # 리스 만료 기간

• 서비스 디스커버리

msa에서 각 서비스의 위치를 동적으로 관리/맵핑하는 기능

  • 서비스 별로 자기 위치 등록
  • 타 서비스에서 이 위치를 조회해 통신
  • 서비스 인스턴스 서버의 상태를 주기적으로 확인 (헬스 체크)

» 헬스 체크

  • eureka 서버가 주기적으로 서비스 인스턴스 상태 확인
    -> 엔드포인트 /actuator/health를 기본 사용
  • 장애 발생 시 eureka서버는 해당 인스턴스를 레지스트리에서 제거

» RestTemplate으로 맵핑

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
@RestController
public class MyRestTemplateController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/get-data-rest")
    public String getDataWithRestTemplate() {
        String serviceUrl = "http://my-service/api/data";
        return restTemplate.getForObject(serviceUrl, String.class);
    }
}

» FeignClient로 맵핑

  • FeignClient 내부적으로 ribbon 사용해 로드밸런싱
  • @FeignClient 명시된 interface는 동적 프록시 구현체가 자동 생성됨
	@SpringBootApplication
    @EnableFeignClients
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
	@FeignClient(name = "my-service")
    public interface MyServiceClient {
    
        @GetMapping("/api/data")
        String getData();
    }
    @RestController
    public class MyFeignClientController {
    
        @Autowired
        private MyServiceClient myServiceClient;
    
        @GetMapping("/get-data-feign")
        public String getDataWithFeignClient() {
            return myServiceClient.getData();
        }
    } 

• 자기 보호 모드

네트워크 통신상의 문제등으로 인해, 실제 서비스 인스턴스 장애가 아니지만 잠깐 헬스 체크가 안되는지 자동 확인하는 기능
-> 개발/테스트 환경등에선 장애등을 빨리 파악하기 좋게 비활성화

작동 방식

  • heartbeat 수신율이 감소시, eureka 레지스트리에서 서비스 인스턴스를 바로 삭제하지 않고 유지

  • 좀 더 오랜시간 관찰, 다시 신호 오면 재등록없이 정상상태 간주

  • 일정시간 지나도 안오면 서비스 장애로 간주

  • eureka.instance.lease-expiration-duration-in-seconds 설정에 따라 이 시간 결정 (default:90초)

profile
Software Engineer

0개의 댓글