일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 주린이
- 기업분석
- 주식
- 프로그래머스
- StringBuffer
- 객체지향
- 무디스
- XLF
- 미국주식
- object
- S&P500
- 오버라이딩
- FCF
- 접근제어자
- 현금흐름표
- 제태크
- 인플레이션
- 배당성장
- 금리인상
- javascript
- 백준
- 잉여현금흐름
- 그리디 알고리즘
- Java
- mco
- etf
- 다형성
- 자바
- 알고리즘
- 금리인하
- Today
- Total
오늘의하루
[Spring Cloud 1일차] Eureka 연동 및 API Gateway 설정과 필터링 본문
서버 포트 번호 설정: server.port = 0
Spring Boot에서 server.port=0으로 설정하면, 서버는 자동으로 사용 가능한 랜덤 Port 번호를 할당한다.
이는 Spring Cloud에서 특히 유용하며 여러 애플리케이션 인스턴스를 각기 다른 Port로 실행해 Eureka와 같은 서비스 등록 서버에 유연하게 등록할 수 있다.
Eureka 연동 시 랜덤 Port 번호 문제점
Eureka는 기본적으로 Host 이름과 Port 번호를 결합하여 인스턴스를 등록하는데 포트가 0으로 설정하면 포트번호가 0번으로 등록되어서 같은 Host 이름을 가지게 되면 몇 개를 등록해도 1개만 등록된 것처럼 보이는 문제점이 있다.
이를 해결하기 위해 고유한 인스턴스 ID 설정이 필요하다. [Eureka Client 설정 방법 참고]
Eureka 서버 설정
Eureka 서버는 다른 서비스 인스턴스들을 중앙에서 관리하고 등록하는 역할을 한다.
1. 의존성 주입
Spring Boot의 pom.xml 또는 build.gradle 파일에 Spring Cloud Discovery의 Eureka Server 의존성을 추가한다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
}
2. Main Class 설정
@EnableEurekaServer 어노테이션을 추가하여 애플리케이션을 Eureka 서버로 설정한다.
@SpringBootApplication
@EnableEurekaServer
public class JangtoApplication {
public static void main(String[] args) {
SpringApplication.run(JangtoApplication.class, args);
}
}
3. application.yml 파일 설정
Eureka 서버는 기본적으로 포트 8761에서 실행된다.
server:
port: 8761
spring:
application:
name: jangto
eureka:
client:
register-with-eureka: false
fetch-registry: false
- Eureka는 웹 서비스 성격으로 기동 되므로 Port 번호를 지정한다.
- register-with-eureka ( 기본값 : true )
- Eureka 서버에 자신을 서비스 레지스트리에 등록할지 여부
- Eureka 서버는 등록할 필요가 없기 때문에 false
- fetch-registry ( 기본값 : true )
- Eureka 서버로부터 인스턴스들의 정보를 주기적으로 가져올 것인지 설정하는 속성
- Eureka 서버는 필요가 없기 때문에 false
추가 ) application.properties 설정
server.port: 8761
spring.application.name:jangto
eureka.client.register-with-eureka: false
eureka.client.fetch-registry: false
Eureka Client 서버 설정
Eureka Client는 서비스가 Eureka 서버에 등록되어야 다른 서비스들이 이 서비스를 호출할 수 있다.
1. 의존성 주입
Spring Boot의 pom.xml 또는 build.gradle 파일에 Spring Cloud Discovery의 Eureka Discovery Client 의존성을 추가한다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
}
2. Main Class 설정
@EnableDiscoveryClient 어노테이션을 추가하여 애플리케이션을 Eureka Client로 설정한다.
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
3. application.yml 파일 설정
server:
port: 0
spring:
application:
name: user-service
eureka:
instance:
instance-id: ${spring.cloud.client.hostname}:${spring.application.instance_id:${random.value}}
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:8761/eureka
- eureka.instance.instance-id : Eureka에서 인스턴스를 구분하는 ID값
- ${spring.cloud.client.hostname} : 현재 host name
- ${spring.application.instance_id:${random.value}} : 인스턴스 ID 값이 없다면 랜덤 값
- 현재 EurekaClient의 Port 번호가 0번으로 되어있기 때문에 고유한 값이 필요
- register-with-eureka : 해당 Client 서버를 Eureka 서버에 등록한다.
- fetch-registry : 다른 서비스 레지스트리 정보를 주기적으로 가져온다.
- defaultZone
- Eureka 서버의 URL을 설정하여 Eureka 서버와 연결할 수 있다.
- 이는 해당 application을 Eureka에 등록하거나 다른 application 정보를 가져올 때 사용된다.
API Gateway
API Gateway는 Client의 요청을 받아 적절한 마이크로서비스로 라우팅 하는 역할을 한다.
API Gateway 설정 방법
1. 의존성 주입
Spring Boot의 pom.xml 또는 build.gradle 파일에 Spring Cloud Routing의 Gateway 의존성을 추가한다.
dependencies {
// 아래 중 원하는 것을 하나 선택하여 의존성 주입
// Netty 가동 (비동기)
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
// Tomcat 가동 (동기) - 기본값
implementation 'org.springframework.cloud:spring-cloud-starter-gateway-mvc'
}
2. application.yml 파일 설정
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
cloud:
gateway:
// Tomcat으로 구동하는 경우 mvc: 필요
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
- routes : Gatway에서 설정한 각 서비스로 요청을 전달하는 라우트 모음
- 이 설정은 JAVA 단에서 설정할 수 있다.
- id : Route의 고유 식별자
- uri : 요청이 매칭되었을 경우 전달될 대상 서버의 URI
- predicates : 지정된 경로와 일치하는 요청을 해당 서비스로 Routing
주의 사항
기본적으로 클라이언트가 http://localhost:8000/first-service/helloworld로 요청을 보내면 Gateway는 이 요청을 http://localhost:8081/first-service/helloworld로 라우팅 한다.
추가) Routes 설정을 JAVA 코드로 설정
1. application.yml 설정
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
2. Route 등록
@Configuration
public class RouteConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r.path("/first-service/**")
.uri("http://localhost:8081"))
.route(r -> r.path("/second-service/**")
.uri("http://localhost:8082"))
.build();
}
}
API Gateway Filter 설정
API Gateway에서 필터를 통해 요청 및 응답을 수정할 수 있으며 Filter는 application.yml 또는 Java 코드에서 설정할 수 있다.
1. application.yml로 설정하는 방법
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
cloud:
gateway:
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
- AddRequestHeader=first-request, first-request-header2
- AddResponseHeader=first-response, first-response-header2
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
- AddRequestHeader=second-request, second-request-header2
- AddResponseHeader=second-response, second-response-header2
- filters : 해당 라우터에서 실행할 필터를 작성할 수 있다.
- AddRequestHeader=key, value : 요청 헤더를 추가
- AddResponseHeader=key, value : 응답 헤더를 추가
Spring 공식 블로그에서 yml에서 설정할 수 있는 다양한 필터 사용법이 소개되어 있다.
2. Route와 Filter를 JAVA 코드로 설정
application.yml에서 routes 설정을 제거하고 Java 코드에서 Filter와 Route를 설정하는 방법이다.
@Configuration
public class FilterConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
return
builder.routes()
.route(r -> r.path("/first-service/**")
.filters(f -> f.addRequestHeader("first-request", "first-request-header")
.addResponseHeader("first-response", "first-response-header"))
.uri("http://localhost:8081"))
.route(r -> r.path("/second-service/**")
.filters(f -> f.addRequestHeader("second-request", "second-request-header")
.addResponseHeader("second-response", "second-response-header"))
.uri("http://localhost:8082"))
.build();
}
}
3. Filter를 별도로 Java 코드로 설정 후 application.yml에 적용
필터를 Java 코드로 정의하고, 이를 application.yml에서 적용하는 방법이다.
1. Filter 등록
// 외부 클래스
public class Config {}
---------------------
@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<Config> {
public CustomFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// custom pre filter
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Custom Pre Filter : request id = {}", request.getId());
request.mutate().header("custom-header-key", "custom-header-value");
// custom post filter
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("Custom Post Filter : request code = {}", response.getStatusCode());
}));
};
}
}
serverHttpRequest는 불변 객체이기 때문에 해당 request에 직접적으로 수정하는 것은 불가능하기 때문에 mutate()를 통해 해당 불변객체를 복사하여 수정하여야 한다.
2. application.yml에 적용
Java로 만든 필터들을 원하는 Route에 적용시킬 수 있다.
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
cloud:
gateway:
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
- CustomFilter
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
- CustomFilter
4. Global Filter 설정 방법
Global Filter는 Spring Cloud Gateway에서 모든 라우트에 대해 공통적으로 적용되는 필터이며 Global Filter는 모든 요청과 응답에 대해 적용된다.
기본적으로 순서는 default Filter(request) -> Custom Filter(request) -> Custom Filter(response) -> default Filter(response)이지만 이런걸 무시하고 순서를 결정할 수도 있다.
1. Global Filter 등록
// 필터 순서 지정 x
@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {
public GlobalFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
// global pre filter
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Global Filter baseMessage : {}", config.getBaseMessage());
if(config.isPreLogger()) {
log.info("Global Filter Start : request id = {}", request.getId());
}
// global post filter
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if(config.isPostLogger()){
log.info("Global Filter End : request code = {}", response.getStatusCode());
}
}));
};
}
// application.yml에서 초기값을 세팅할 수 있다.
@Data
public static class Config {
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
-----
// 필터 순서 지정 O : 0번이라는 순서를 지정
@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {
public GlobalFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return new OrderedGatewayFilter((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Global Filter baseMessage : {}", config.getBaseMessage());
if(config.isPreLogger()) {
log.info("Global Filter Start : request id = {}", request.getId());
}
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if(config.isPostLogger()){
log.info("Global Filter End : request code = {}", response.getStatusCode());
}
}));
}, 0);
}
@Data
public static class Config {
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
2. application.yml에 적용
server:
port: 8000
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: apigateway-service
cloud:
gateway:
default-filters:
- name: GlobalFilter
args:
# GlobalFilter.Config 초기값 세팅
baseMessage: Spring Cloud GateWay Global Filter
preLogger: true
postLogger: true
routes:
- id: first-service
uri: http://localhost:8081/
predicates:
- Path=/first-service/**
filters:
- CustomFilter
- id: second-service
uri: http://localhost:8082/
predicates:
- Path=/second-service/**
filters:
- CustomFilter
- default-filters: 모든 라우트에 기본적으로 적용할 필터를 설정이다.
- name : Global Filter로 사용할 클래스 명을 작성한다.
- args
- key: value 형식으로 작성하며 여기서 작성된 key값과 AbstractGatewayFilterFactory의 제네릭 타입 파라미터 객체의 속성과 일치한다면 해당 value로 초기화해 준다.
- 만약 key가 없다면 무시된다.
'Spring > Cloud' 카테고리의 다른 글
[Spring Cloud 2일차] API Gateway 필터 순서 및 Eureka Load Balancing (0) | 2024.09.11 |
---|