기존에 있던 모놀리식 아키텍처를 msa 로 구현해보는 과정에서
API Gateway 로 Spring Cloud 를 이용하기로 했다.
그전에 MSA와 DevOps, K8S 등의 개념을 알고 가는게 좋을꺼 같아 퍼왔다. 참조하면 좋을꺼같다.
https://happycloud-lee.tistory.com/261?category=8322466
✔ 서비스 디스커버리(Service Discovery)
서비스 인스턴스의 네트워크 위치를 찾고 로드밸런싱하는 역할하는 놈을 보고 서비스 디스커버리라 한다.
내가 구성한 각각의 독립적인 모듈 API 끼리의 통신은 보통 REST API로 통신한다.
요청을 보내기 위해서는 서비스 인스턴스가 있는 곳의 네트워크 정보를 알아야 한다(IP,PORT주소)
물리적 서버에서 돌아가는 경우라면 미리 설정 파일로 빼서 관리하면 되니 크게 문제는 없다.
하지만 클라우드에서 인스턴스는 동적으로 할당되기 때문에 IP주소나 포트 정보가 정해지지 않은 데다가 오토스케일링도 일어나고 중지되고 복구되면서 네트워크 위치가 계속해서 바뀐다.
따라서 클라이언트나 API 게이트웨이가 호출할 서비스를 찾는 매커니즘이 필요하다. 그래서 이게 필요한거임.
자세한설명은 2탄참조
https://ssmyefrin.tistory.com/51
그리고 나는 이걸 Spring Cloud 를 이용하여 구현해보겠다.
✔ Spring Cloud
Spring Cloud는 마이크로서비스의 개발, 배포, 운영에 필요한 아키텍처를 쉽게 구성할 수 있도록 지원하는
Spring Boot기반의 프레임워크다. 다시 말해 "MSA구성을 지원하는 Springboot기반 Framework" 다.
Spring Cloud의 핵심 component는 아래와 같이 요약할 수 있다.
그림이 너무 어렵다.
일단 나도 100%완벽하게 이해는 못했으니 넘어가고, 찬찬히 실습해보면서 이해해보려 한다.
구현할 어플리케이션 목록이다.
- DiscoveryServer : 각 어플리케이션의 정보가 등록되어, 로드 밸런서 역할을 한다.
- GatewayServer : 모든 요청이 거쳐가는 진입로가 된다.
- BackendService: 실제 호출에 대한 응답을 하게 된다.
실습환경
- IntelliJ + JDK 17 + SpringBoot 3.1.5 + Gradle
- Spring Cloud
- MacOS
✔ 디스커버리 서버(유레카 서버) 만들기
- 아, 참고로 유레카 서버는 넷플릭스에서 MSA를 위해 Spring Cloud에 기부한 오픈 소스이다.(ㄱㅅㄱㅅ)
1. Project 생성
혹은 build.gradle 에 아래 Dependency 추가
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
2. application.yml 설정 파일에 추가
유레카 서버로서 동작할 수 있도록 코드를 작성
spring:
application:
name: eureka_server # 애플리케이션 이름
server:
port: 8761
eureka:
instance:
hostname: localhost
# Eureka Client 설정
client:
registerWithEureka: false # 유레카에 등록할지 여부. 자기 자신을 등록할 필요가 없다.
fetchRegistry: false # Eureka 서버로부터 받은 서비스 리스트에 대한 캐싱여부
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 유레카 서버의 주소 지정
# Eureka Server 설정
server:
waitTimeInMsWhenSyncEmpty: 0 # 유레카 서버가 동기화 대기시간 지정. 0으로 설정되어 있어 즉시 동기화를 시도
response-cache-update-interval-ms: 5000 # 유레카 서버 응답 캐시 업데이트 간격 지정
management.endpoints.web.exposure.include: "*" # 모든 관리 엔드포인트를 노출하도록 지정
spring.application.name
Eureka 서버에서 서비스를 식별하는 id이다.
eureka.client.register-with-eureka
유레카 서버에 자기 자신을 클라이언트로 등록하지 않도록 하는 설정이다.
본 프로젝트는 디스커버리 서버 역할을 하는 유레카 서버이므로 자기 자신을 클라이언트로써 디스커버리 서버에 등록하지 않도록 false로 설정한다.
eureka.client.fetch-registry
클라이언트로써 eureka 서버에서 eureka 레지스트리 정보를 가져올지 여부를 설정한다.
위 설정과 마찬가지로 클라이언트가 아니므로 false로 설정한다.
3. @EnableEurekaServer 로 유레카 서버 명시
유레카 서버로 동작하게끔 메인 애플리케이션에 어노테이션인 @EnableEurekaServer를 추가해준다.
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
4. 서버 구동후 http://localhost:8761/ 접속
✔ GatewayServer 만들기
이 서버의 역할은 클라이언트와의 통신, BackendService에 대한 리버스 프록시(Reverse Proxy)-라우팅 을 하게 된다.
1. Project 생성
혹은, 아래 의존성추가
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
게이트웨이스타터를 추가하지 않았더니, 라우팅 자체가 안된다(이걸로 삽질 엄청함ㅠㅠ)
2. application.yml 에 추가
server:
port: 8003
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka # DiscoveryServer 지정
spring:
application:
name: gateway-server2 # 설정한 이름대로 DiscoveryServer 에 서비스가 등록
cloud:
gateway:
# Gateway 라우팅 설정
routes:
- id: backend-service # 라우팅할 서비스이름
uri: lb://BACKEND-SERVICE # Eureka에 등록된 backend-service 리버스 프록시(대문자로되어있을꺼임)
predicates:
- Path=/backend/** # 요청이 들어오면 backend-service 전달되도록 설정
filters:
- RewritePath=/backend/(?<segment>.*),/$\{segment} # /backend 로 시작하는 패스를 재작성
3. @EnableDiscoveryClient 애노테이션을 추가하여 유레카 클라이언트로 동작하게끔 한다.
@EnableDiscoveryClient
@SpringBootApplication
public class ApiGateway2Application {
public static void main(String[] args) {
SpringApplication.run(ApiGateway2Application.class, args);
}
}
✔ BackendService 생성(실제서비스 생성)
1. Project 생성(생략)
의존성 추가
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.boot:spring-boot-starter-web'
2. application.yml 생성
server:
port: 8002
spring:
application:
name: backend-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
instance:
preferIpAddress: true
3. 구동에 어노테이션 추가
@EnableDiscoveryClient
@SpringBootApplication
public class TodoApiApplication {
public static void main(String[] args) {
SpringApplication.run(TodoApiApplication.class, args);
}
}
유레카 서버 접속
API 로 확인해보기
- 마이크로서비스에서 직접 날렸을 때
- 게이트웨이를 통해 날렸을때
위와같이 결과가 똑같다는걸 알 수 있음.
참조:
https://www.devkuma.com/docs/spring-cloud/quick-guide/#google_vignette
'web' 카테고리의 다른 글
[JAVA] Stream for each vs for-loop (0) | 2024.06.11 |
---|---|
[WEB] 블로킹/논블로킹 and 동기 / 비동기 (0) | 2023.11.23 |
[WEB][Reactor Java] Mono와 Flux를 생성하는 방법 (1) | 2023.11.08 |
[WEB] Reactive Streams (1) | 2023.11.08 |
HTTP 인증에 대한 처리 방식 (0) | 2023.08.22 |