해당 포스트는 Spring Cloud에 속한 기술들에 대한 개념과 주요 기술에 대해 알아보고 실무에 적용했었던 내용을 정리하는 포스트입니다.
MSA에서 마이크로서비스 관리와 운영을 위한 패턴 중 서비스 레지스트리와 서비스 디스커버리가 있습니다.
서비스 간 통신 시 서비스 위치 (포트, 호스트) 가 정적이던 전통적인 어플리케이션 / 아키텍처와는 달리 주소가 동적으로 변화하고 (클라우드 환경, 오토 스케일링, 컨테이너 기반의 배포 등) 서비스 역시 무수히 많은 마이크로서비스에서는 서비스 위치에 대한 관리가 많이 복잡해지게 되는데, 이를 해결하기 위해 서비스 레지스트리 패턴과 서비스 디스커버리 패턴이 등장하게 됩니다.
서비스 레지스트리와 서비스 디스커버리 패턴에 대한 설명은 다음과 같습니다.
Spring Cloud Eureka는 서비스 레지스트리와 서비스 디스커버리를 지원하기 위한 라이브러리이며 서버 / 클라이언트로 나뉩니다.
application.yml을 다음과 같이 설정합니다.
레지스트리에서는 각 서비스의 이름을 식별할 때 spring.application.name
에 작성된 명칭으로 식별을 합니다.
server:
port: 8761
spring:
application:
name: test-eureka-local
config:
activate:
on-profile: local
eureka:
instance:
prefer-ip-address: true
server:
enable-self-preservation: true
client:
register-with-eureka: false # 자기 자신을 서비스로 등록하지 않음
fetch-registry: true # 마이크로서비스 인스턴스 목록을 로컬에 캐시할 것인지 여부. 서비스 탐색 등의 목적.
service-url:
defaultZone: http://localhost:8761/eureka
management:
security:
enabled: false
ribbon:
IsSecure: false
security:
basic:
enabled: true
user:
name: user
password: secret
이후 어플리케이션의 메인 클래스에 @EnableEurekaServer
어노테이션을 부착합니다.
@EnableEurekaServer
@SpringBootApplication
public class ModuleEurekaApplication {
public static void main(String[] args) {
SpringApplication.run(ModuleEurekaApplication.class, args);
}
}
서버 실행 후 접속 (로컬이므로 http://localhost:8761) 을 하여 서비스 인스턴스들을 확인할 수 있습니다.
application.yml을 다음과 같이 설정합니다.
위에서 설명한 대로 spring.application.name
을 통해 레지스트리 측에 전달할 서비스의 이름을 지을 수 있습니다.
또한, eureka.instance.instance-id
의 값을 통해 인스턴스 고유 ID 표기 방식을 변경할 수 있습니다.
(기본값은 호스트 + 어플리케이션 이름 + 포트 번호)
eureka.client.serviceUrl.defaultZone
은 Eureka Server의 주소 + /eureka/ 입니다.
# 각 마이크로서비스 공통 사항
spring:
application:
name: 마이크로서비스 이름
...
eureka:
instance:
instance-id: ${spring.cloud.client.hostname}:${spring.application.instance_id:${random.value}}
leaseRenewalIntervalInSeconds: 10
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
이후 어플리케이션의 메인 클래스에 @EnableDiscoveryClient
어노테이션을 부착합니다.
@EnableDiscoveryClient
@SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
이렇게 클라이언트 측에서 세팅을 할 경우 Eureka Server를 다시 확인하면 서비스가 정상적으로 등록되어있음을 확인할 수 있습니다.
Spring Cloud OpenFeign과의 연계
https://velog.io/@mrcocoball2/Spring-Cloud-Spring-Cloud-OpenFeign-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EB%B0%8F-%ED%99%9C%EC%9A%A9
이전 게시글에서는 Ribbon을 사용하지 않았으며 서비스 이름을 식별하지 못해 url을 직접 사용했었지만 Eureka Server / Client를 통해 서비스 이름을 식별할 수 있게 됩니다.
@EnableDiscoveryClient
어노테이션을 메인 클래스에 부착한 후 이전에 LoadBalancer나 Ribbon을 사용하지 않아 기본 클라이언트를 설정했던 설정 클래스를 주석 처리 합니다.
@Configuration
public class FeignConfig {
/*
@Bean
public Client feignClient() {
return new Client.Default(null, null);
}
*/
}
그리고 url로 동기 통신 대상(localhost:8081)을 지정하던 인터페이스 설정을 서비스 이름(sample)으로 대체합니다.
// @FeignClient(url = "http://localhost:8081")
@FeignClient(name = "sample")
public interface SampleClient {
@GetMapping("/api/v1/internal/sample/cases")
ResponseEntity<List<CaseDTO>> getCaseList(@RequestHeader("Internal-Auth-Token") String token);
@GetMapping("/api/v1/internal/sample/cases/{id}")
ResponseEntity<CaseDTO> getCase(@RequestHeader("Internal-Auth-Token") String token,
@PathVariable("id") Long id);
}
Spring Cloud Gateway와의 연계
https://velog.io/@mrcocoball2/Spring-Cloud-Spring-Cloud-Gateway-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90
이전 게시글에서는 url로 직접 라우팅을 하였지만, lb://서비스 이름
으로 라우팅 및 로드 밸런싱이 가능해집니다.
@EnableDiscoveryClient
어노테이션을 메인 클래스에 부착한 후 기존 application.yml을 수정합니다.
spring:
cloud:
gateway:
# 먼저 선언한 순서대로 필터가 적용됨 route 1 -> route 2
routes:
# route 1, route의 id는 sample-internal
- id: sample-internal
#uri: http://localhost:8081
uri: lb://sample
predicates:
- Path=/sample/api/v1/internal/** # /sample/api/v1/internal/** 로 들어오는 요청에 반응
filters:
- NotAllowedURIExceptionFilter # filter 로직 적용 (커스텀 필터)
# route 2, route의 id는 sample
- id: sample
#uri: http://localhost:8081
uri: lb://sample
predicates:
- Path=/sample/** # /sample/** 로 들어오는 요청에 반응
filters:
- RewritePath=/sample/(?<segment>.*), /$\{segment} # filter 로직 적용 (RewritePath 필터)
여기서 라우팅되는 하위 마이크로서비스 측에서 주소나 포트를 변경한 후 다시 실행하더라도 일정 시간 단위로 Eureka Server에서 핑을 보내 마이크로서비스의 정상 작동 여부를 확인하고 이용할 수 없는 서비스 정보는 삭제, 다시 실행된 마이크로서비스의 정보가 레지스트리에 등록되어 갱신되기 때문에 Gateway에서 정보를 바꾸지 않더라도 서비스 연결이 가능해집니다.
https://cloud.spring.io/spring-cloud-netflix/reference/html/