BackEnd/Spring MSA

[Spring cloud 기반 MSA 맛보기] - Eureka를 사용해보자

영지는 달리는중 2020. 9. 7. 18:22

Ribbon를 소개하는 이전 포스팅의 마무리에서 Eureka와 함께 사용하면 로드밸런싱이 더 효과적이라고 언급하였다

Eureka란 무엇이고 이를 직접 사용하여 실습을 해보도록하자

1. Eureka란?

서버가 새롭게 시작되면 그것을 감지하여 목록에 자동으로 추가하고, 서버가 종료되면 자동으로 목록에서 삭제하는 기능을 제공하는 라이브러리

  • Service Registry기능 수행
    • 컴퓨터 네트워크에서 장치 및 서비스를 자동으로 검색(감지)하여 정보를 담고있는 데이터베이스 - Dynamic Service Discovery
    •  클라우드의 전화번호부라고 생각하면 된다(유레카의 경우 유레카 클라이언트들의 정보가 저장)
  • DiscoveryClient
    • Spring-cloud에서 서비스 레지스트리 사용 부분을 추상화한 인터페이스
    • Eureka, Consul, Zookeeper 등의 구현체가 존재한다

Ribbon을 사용하여 실습을 하였을 때 만약 서버가 늘어난다면 yml파일의 listOfServers에 서버를 직접 추가하여야했다

이렇게 직접 추가하는 작업을 자동화하는 기능을 제공하는 라이브러리가 Eureka 라이브러리이다

 

2. 유레카서버 - 유레카 클라이언트 간의 작동 과정

  • 유레카 클라이언트는 자신을 유레카 서버에 등록하고 호스트, 포트, 상태 정보 URL, 홈페이지 URL을 전송
  • 유레카 클라이언트는 heartbeat (생존신호) 메시지를 전송
  • 유레커 서버는 heartbeat 메시지를 받지 못하면 레지스트리에 해당 클라이언트를 삭제
  • 클라이언트는 서버로부터 레지스트리 목록을 가져와서 캐싱하고 주기적으로 변경사항 점검

3. 유레카(디스커버리) 서버의 특징 - 복제와 고가용성

  • 디스커버리 서버의 장애에 대비해 적어도 두 개의 디스커버리 서버를 구성한다
  • 유레카 디스커버리 서버는 다른 디스커버리 서버 간의 peer-to-peer 모델 기반으로 구성되어있다. 이는 모든 서버가 현재 서버 노드에 모든 서버에게 데이터를 복제하고 하트비트를 보낸다는 것을 의미한다

Eureka server & Eureka Client 설정

 

1. Eureka Server(Registry) 만들기 

 

라이브러리 의존성

dependencies {
    compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

메인 클래스에 @EnableEurekaServer 어노테이션 추가

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

 application.yml 설정

server:
  port: 8761 # Default
spring:
  application:
    name: eureka-server
eureka:
  server:
    response-cache-update-interval-ms: 1000 # eureka client 에게 자신의 registery 정보 응답 시 사용하는 캐시의 속도, 빠른 정보제공을 위해 캐시 사용 - 기본30초이지만 개발 편의를 위해 1초로 변경
    enable-self-preservation: false #자기 보호 모드(네트워크 장애 발생시 eureka client와 통신되지 않아도 해당 cleint를 해제되는 것을 방지 - 개발시에만 비활성화)
  client:
    register-with-eureka: false # 본인 서비스를 eureka 서버에 등록할지 여부 - 디스커버리 서버가 두개 이상일 경우에만 true 로 설정해야 함 - 개발모드
    fetch-registry: false # Eureka client가 registry 정보를 로컬에 caching 할지 여부 - eureka 서버이므로 비활성화
    service-url:
      defaultZone: http://localhost:8761/eureka # http://${eureka.instance.hostname}:${server.port}/eureka/
    instance:
      prefer-ip-address: true # 서비스간 통신 시 hostname 보다 ip 를 우선 사용 - 개발모드(DNS가 아직 없으므로)

 

각 설정에 대한 기능은 주석을 참고

 

2. Eureka Client 설정하기 

라이브러리의존성 추가

    compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') // 3. To use Eureka client

 

등록하려는 마이크로서비스의 메인클래스에 @EnableEurekaClient 어노테이션을 추가

-> @EnableDiscoveryClient를 사용할 경우 eureka가 아닌 다른 구현체들도 사용 가능하다 

@SpringBootApplication
@EnableCircuitBreaker
@EnableEurekaClient
public class DisplayApplication {

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

    public static void main(String[] args) {
        SpringApplication.run(DisplayApplication.class);
    }

}

application.yml 파일 변경

product:
  ribbon:
    MaxAutoRetries: 0
    MaxAutoRetriesNextServer: 1

eureka:
  instance:
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka 
  • Eureka 서버로부터 마이크로서비스 목록을 가져올 것이므로 listOfServers를 제거한다
  • ribbon은 Neflix가 제공하는 라이브러리를 사용하여 여러가지 설정을 할 수 있다
  • prefer-ip-address: DNS(domain name system)이 없는 개발단계이므로 ip를 활성화해준다

고급 Configuration 설정

  • Server : eureka.server.*, 서버 관련 설정
  • Client : eureka.client.*, 클라이언트가 레지스트리에서 다른 서비스의 정보를 얻을 수 있는 설정
  • Instance : eureka.instance.*, 포트나 이름 등의 현재 유레카 클라이언트의 행동을 재정의하는 설정
    • 예시 - eureka.instance.lease-renewal-interval-in-seconds: 1 , 유레카 서버에게 1초마다 하트비트를 전송하도록 설정
    • 예시2 - eureka.instance.expiration-duration-in-seconds: 2, 유레카 서버는 서비스 등록을 해제하기 전 마지막 하트비트에서부터 2초를 기다림

클라이언트에서 등록된 서비스 목록 출력하는 API

@RestController  
public class TestController {  
	private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);
	
	@Autowired  
	private DiscoveryClient discoveryClient;  
	
	@GetMapping("/ping")  
	public List<ServiceInstance> ping() {  
		List<ServiceInstance> instances = discoveryClient.getInstances("CLIENT-SERVICE");  
		LOGGER.info("INSTANCES: count = {}", instances.size());  
		instances.forEach(it -> LOGGER.info("INSTANCE: id={}, prot={}", it.getServiceId(), it.getPort()));  
		return instances;  
	}  
}

마무리

 

Ribbon을 사용한 클라이언트 사이드 로드밸런싱을 수행 할 때 서버의 추가와 제거를 직접하는 것이 아닌 Eureka 서버를 통해 자동화한다

Eureka 서버를 생성하고 클라이언트로 등록하고싶은 서비스에 @EnableEurekaClient 어노테이션을 추가하여 자신의 상태를 등록한다

주기적으로 HeartBeat로 Eureka 서버에 자신이 살아있음을 알린다

서버 종료시 Eureka 서버에 자신의 상태를 변경 혹은 삭제한다(자동)

Eureka 서버는 이중화하는 것을 추천한다

 

참고한 블로그