1. 개요
현재 배울 CustomFilter 생성 및 등록을 통해서 PreFilter와 PostFilter를 GateWay 단에서 적용 시킬 수 있다.
2. CustomFilter
다음과 같은 CustomFilter를 생성한다.
참고로 다음과 같은 CustomFilter를 ApiGateWay에 적용하기 위해서는 yml에 등록해줘야 한다.
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
public CustomFilter() {
super(Config.class);
}
public GatewayFilter apply(Config config) {
return null; // 당연히 수정해야겠지?
}
public static class Config {
}
}
CustomFilter → Application.yml에 등록하기
내가 만든 CustomFilter를 어느 마이크로 서비스에 거치도록 할 지 정한다.
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 적용
- CustomFilter
- id: second-service
uri: <http://localhost:8082/>
predicates:
- Path=/second-service/**
filters: # CustomFilter 적
- CustomFilter
결과물
First-Service와 Second-Service를 ApiGateway를 통해 접속할 때 마다 다음과 같이 로그 출력!
package com.msa.apigatewayservice.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
public CustomFilter() {
super(Config.class);
}
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());
// Custom Post Filter
// 비동기 방식 + 단일값 반환에는 Mono 객체 사용
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("Custom POST Filter: response id -> {}", response.getStatusCode());
}));
};
}
public static class Config {
}
}
3. GlobalFilter
어느 마이크로 서비스에 등록할지에 대한 CustomFIlter 대신, 전역적으로 등록하여 모든 요청의 처음와 모든 응답의 마지막에 적용되는 GlobalFilter를 적용해보자
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {
public GlobalFilter() {
super(Config.class);
}
public GatewayFilter apply(Config config) {
// Custom 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());
}
// Custom Post Filter
// 비동기 방식 + 단일값 반환에는 Mono 객체 사용
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if (config.isPostLogger()) {
log.info("Global Filter End: response id -> {}", response.getStatusCode());
}
}));
};
}
@Data
public static class Config { // 필드 값은 yml 에서 주입받는다.
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
application.yml (apigateway-serivce)
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:
baseMessage: Spring Cloud Gateway Global Filter baseMessage
preLogger: true
postLogger: true
routes:
- id: first-service
uri: <http://localhost:8081>
predicates:
- Path=/first-service/**
filters:
- CustomFilte
- id: second-service
uri: <http://localhost:8082/>
predicates:
- Path=/second-service/**
filters:
- CustomFilter
적용 결과
default-filters에 등록된 GlobalFilter가 클라이언트 요청에 대해서 필터들 중 가장 먼저 작동되고 응답에 대해서는 가장 나중에 작동된다.
- request id 또한 같은 걸 확인할 수 있다. (하나의 요청에 대한 출력 콘솔)
4. 배운 것들
apigateway-service에서 Custom Filter와 Global Filter를 등록해 여러 마이크로 서비스에 등록하는 과정을 공부했다!
'MSA 공부' 카테고리의 다른 글
API Gateway Service - 1 (0) | 2025.01.26 |
---|---|
Service Discovery (0) | 2025.01.26 |