자세한 건 노션에 적었고 복습하는 겸 간단하게 MSA 강의 들은 것, 크게 Eureka, 로드 밸런싱, Gateway, Config Server만 정리!
1. Eureka
MSA에서 각 서비스 위치를 동적으로 관리하는 디스커버리 서버
1) Eureka Server
- Eureka Server의 Application.java에 @EnableEurekaServer 어노테이션 추가
- application.properties에 설정 정의
spring.application.name=server
server.port=19090
# 유레카 서버에 자신을 등록할지 여부를 설정함.
# 유레카 서버에서는 일반적으로 false로 설정하여, 서버가 자기 자신을 등록하지 않도록 함.
eureka.client.register-with-eureka=false
# 유레카 서버로부터 레지스트리를 가져올지 여부를 설정함.
# 유레카 서버에서는 일반적으로 false로 설정하여, 레지스트리를 가져오지 않도록 함.
eureka.client.fetch-registry=false
# 유레카 서버 인스턴스의 호스트 이름을 설정, 유레카 서버가 자신의 호스트 이름을 다른 서비스에 알릴 때 사용함.
eureka.instance.hostname=localhost
# 유레카 클라이언트가 유레카 서버와 통신하기 위해 사용할 기본 서비스 URL을 설정함.
# 클라이언트 애플리케이션이 유레카 서버에 연결하고 등록하거나 레지스트리를 가져올 때 사용할 URL을 지정함.
eureka.client.service-url.defaultZone=http://localhost:19090/eureka/
2) Eureka Client
➡️ 여기다가 만들어놓은 서비스를 등록해야 다른 서비스 호출할 때 Eureka Server를 쓸 수 있음.
- application.properties
// first
spring.application.name=first
server.port=19091
# 유레카 클라이언트가 유레카 서버와 통신하기 위해 사용할 기본 서비스 URL을 설정합니다.
# 유레카 서버의 포트와 호스트 이름을 정확히 지정해야 합니다.
eureka.client.service-url.defaultZone=http://localhost:19090/eureka/
// second
spring.application.name=second
server.port=19092
eureka.client.service-url.defaultZone=http://localhost:19090/eureka/
결과
2. 로드 밸런싱 (FeignClient와 Ribbon)
- 로드 밸런싱 : 서버 간 트래픽을 고르게 분배해 특정 서버 부하 방지
- 클라이언트 사이드 로드 밸런싱 : 클라이언트가 직접 서버 골라서 요청 보내는 방식
- FeignClient : Spring Cloud 제공 HTTP 클라이언트로 선언적으로 RESTful 웹 서비스를 호출할 수 있음.
- Ribbon : 클라이언트 사이드 로드 밸런서로 FeignClient에 통합되어 있음.
1) product-service : 호출당할 놈
- ProductApplication.java에 @EnableFeignClients 어노테이션 추가
- application.yml : spring.application.name과 eureka url을 주목해야 함.
spring:
application:
name: product-service
server:
port: 19092
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
- 포트번호 19092, 19093, 19094에서 같은 애플리케이션(product-service) 실행하기
2) order-service : 호출할 놈
- OrderApplication.java에 @EnableFeignClients 어노테이션 추가
- application.yml은 product-service랑 구성은 같음. 당연히 Eureka 주소도 같겠죠?
- ProductClient 만들기
package com.spring_cloud.eureka.client.order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name="product-service") // product랑 이름이 같아야 함.
public interface ProductClient {
@GetMapping("/products/{id}")
String getProduct(@PathVariable("id") String id);
}
- OrderService에서 이 FeignClient를 주입받아 product-service의 메서드를 호출하는 것
// ProductController
package com.spring_cloud.eureka.client.order;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class OrderController {
private final OrderService orderService;
@GetMapping("/order/{orderId}")
public String getOrder(@PathVariable("orderId") String orderId) {
return orderService.getOrder(orderId);
}
}
// ProductService
package com.spring_cloud.eureka.client.order;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class OrderService {
private final ProductClient productClient;
public String getProductInfo(String productId) {
// 작성한 FeignClient Interface로 product-service의 getProduct 호출
return productClient.getProduct(productId);
}
public String getOrder(String orderId) {
if (orderId.equals("1")) {
String productId = "2";
String productInfo = getProductInfo(productId);
return "Your order is " + orderId + " and " + productInfo;
}
return "Not exist order...";
}
}
3) 실행 결과
3. Gateway
클라이언트의 요청을 받아 백엔드 서비스로 라우팅해주는 단일 진입점 역할을 하고 보안, 로깅, 모니터링, 필터링 등 처리하는 중간 서버
1) Spring Cloud Gateway
- gateway 프로젝트 생성
- build.gradle : gateway 쓰려면 있어야 하는 의존성들...
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
- CustomPreFilter, CustomPostFilter 작성
- application.yml
server:
port: 19091 # 게이트웨이 서비스가 실행될 포트 번호
spring:
main:
web-application-type: reactive # Spring 애플리케이션이 리액티브 웹 애플리케이션으로 설정됨
application:
name: gateway-service # 애플리케이션 이름을 'gateway-service'로 설정
cloud:
gateway:
routes: # Spring Cloud Gateway의 라우팅 설정
- id: order-service # 라우트 식별자
uri: lb://order-service # 'order-service'라는 이름으로 로드 밸런싱된 서비스로 라우팅
predicates:
- Path=/order/** # /order/** 경로로 들어오는 요청을 이 라우트로 처리
- id: product-service # 라우트 식별자
uri: lb://product-service # 'product-service'라는 이름으로 로드 밸런싱된 서비스로 라우팅
predicates:
- Path=/products/** # /product/** 경로로 들어오는 요청을 이 라우트로 처리
discovery:
locator:
enabled: true # 서비스 디스커버리를 통해 동적으로 라우트를 생성하도록 설정
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/ # Eureka 서버의 URL을 지정
2) 실행 결과
4. Auth (생략)
5. Config Server
애플리케이션의 설정(application.yml 등)을 중앙에서 관리하고 변경 사항을 실시간으로 반영할 수 있다.
1) Config Server
- Config Server 프로젝트 생성
- ConfigApplication.java에 @EnableConfigServer 어노테이션 추가
- application.yml
# resources/config-repo 디렉토리 생성
server:
port: 18080
spring:
profiles:
active: native
application:
name: config-server
cloud:
config:
server:
native:
search-locations: classpath:/config-repo # 리소스 폴더의 디렉토리 경로
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
- cofig-repo 디렉토리 내에 product-service.yml, product-service-local.yml 생성
2) Config Client - Product
- build.gradle에 Config Client 의존성 추가
implementation 'org.springframework.cloud:spring-cloud-starter-config'
- application.yml
server:
port: 0 # 임시 포트, 이후 Config 서버 설정으로 덮어씌움
spring:
profiles:
active: local
application:
name: product-service
config:
import: "configserver:"
cloud:
config:
discovery:
enabled: true
service-id: config-server
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
message: "default message"
3) 실행 결과1
- 실시간 구성 변경 방법
- Spring Cloud Bus 사용 → 메시징 시스템을 통해 실시간으로 설정 변경 사항을 전파하는 데 유용함.
- 수동으로 /actuator/refresh 엔드포인트 호출
- Spring Boot DevTools 사용 → 주로 개발 환경에서 유용하게 사용됨.
- Git 저장소 사용 → 설정 파일의 버전 관리 쉬움.
4) /actuator/refresh
- Config > application.yml 수정
server:
port: 0 # 임시 포트, 이후 Config 서버 설정으로 덮어씌움
spring:
profiles:
active: local
application:
name: product-service
config:
import: "configserver:"
cloud:
config:
discovery:
enabled: true
service-id: config-server
management:
endpoints:
web:
exposure:
include: refresh
eureka:
client:
service-url:
defaultZone: http://localhost:19090/eureka/
message: "default message"
- Product > ProductController에 @RefreshScope 어노테이션 추가
- 테스트를 위해 product-service-local.yml 파일 수정 (message에 "update" 문구 추가)
server:
port: 19083
message: "product-service-local message update"
5) 실행 결과2
역시 정리하는 건... 노션이 편한 것 같다...
'TIL' 카테고리의 다른 글
TIL6. Paging, S3 Bucket (0) | 2025.02.18 |
---|---|
TIL5. 카테고리 API 마무리 + Review API 만들기 (2) | 2025.02.17 |
TIL4. PR, PostgreSQL, .env, 카테고리 CRUD (0) | 2025.02.14 |
TIL3. Git Flow (2) | 2025.02.13 |
TIL2. 배달 플랫폼 프로젝트 시작! (0) | 2025.02.12 |