Spring Cloud Gateway에서 사용자 정의 필터를 생성하는 방법을 다뤄보겠습니다.
공통 로직을 FilterUtility 클래스에 정의하여 필터에서 재사용할 수 있도록 했습니다. 이 클래스는 상관 관계 ID를 요청 및 응답 헤더에서 가져오거나 설정하는 역할을 합니다.
GlobalFilter
인터페이스를 구현하여 모든 요청에 대해 필터를 적용했습니다. 필터 체인을 사용해 다음 필터를 호출할 수 있도록 구현했습니다.GlobalFilter
를 구현하는 또 다른 방법으로, 메서드 내에서 GlobalFilter
객체를 생성하고 이를 빈으로 등록했습니다.application.yml
파일에 디버그 로깅을 활성화하는 설정을 추가하여, 필터의 디버그 로그가 출력되도록 했습니다. 이를 통해 필터가 올바르게 작동하는지 확인할 수 있습니다.
@Component
@Order(1)
public class RequestTraceFilter implements GlobalFilter {
private final Logger logger = LoggerFactory.getLogger(RequestTraceFilter.class);
@Autowired
private FilterUtility filterUtility;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
HttpHeaders headers = exchange.getRequest().getHeaders();
if (isCorrelationIdPresent(headers)) {
logger.debug("easybank-correlation-id found in RequestTraceFilter: {}",
filterUtility.getCorrelationId(headers));
} else {
String correlationId = generateCorrelationId();
exchange = filterUtility.setCorrelationId(exchange, correlationId);
logger.debug("easybank-correlation-id generated in RequestTraceFilter: {}", correlationId);
}
return chain.filter(exchange);
}
private boolean isCorrelationIdPresent(HttpHeaders headers) {
return filterUtility.getCorrelationId(headers) != null;
}
private String generateCorrelationId() {
return UUID.randomUUID().toString();
}
}
@Configuration
public class ResponseTraceFilter {
private final Logger logger = LoggerFactory.getLogger(ResponseTraceFilter.class);
@Autowired
private FilterUtility filterUtility;
@Bean
public GlobalFilter postGlobalFilter() {
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
HttpHeaders headers = exchange.getRequest().getHeaders();
String correlationId = filterUtility.getCorrelationId(headers);
logger.debug("Updated the correlation id to the outbound headers. {}", correlationId);
exchange.getResponse().getHeaders().add(FilterUtility.CORRELATION_ID, correlationId);
}));
};
}
}
@Component
public class FilterUtility {
public static final String CORRELATION_ID = "easybank-correlation-id";
public String getCorrelationId(HttpHeaders requestHeaders) {
if (requestHeaders.get(CORRELATION_ID) != null) {
List<String> requestHeaderList = requestHeaders.get(CORRELATION_ID);
return requestHeaderList.get(0);
} else {
return null;
}
}
public ServerWebExchange setCorrelationId(ServerWebExchange exchange, String correlationId) {
return exchange.mutate().request(exchange.getRequest().mutate().header(CORRELATION_ID, correlationId).build()).build();
}
}
logging:
level:
com.eazybytes.gatewayserver: debug
사용자 정의 필터를 생성하여 상관 관계 ID를 생성하고 이를 모든 마이크로서비스 호출에 전달하는 방법을 배웠습니다. 다음 챕터에서는 마이크로서비스 내에서 이러한 상관 관계 ID를 활용하는 방법에 대해 살펴볼 예정입니다.
Gateway 서버를 통해 요청이 전달될 때 각 마이크로서비스에서 요청 헤더를 수락하고 처리하는 방법에 대해 알아봅니다. 이제 모든 마이크로서비스에서 easybank-correlationId
헤더를 처리하여 로깅을 추가하고 이 상관 관계 ID를 활용하는 방법을 살펴보겠습니다.
accounts
, loans
, cards
)의 컨트롤러에서 @RequestHeader
를 사용하여 easybank-correlationId
를 수락하고 이를 로깅에 사용했습니다.AccountsController
에서 다음과 같이 요청 헤더를 수락하고 로깅합니다:@GetMapping("/api/fetchCustomerDetails")
public CustomerDetails fetchCustomerDetails(@RequestHeader(value = "easybank-correlationId", required = false) String correlationId, @RequestParam String mobileNumber) {
logger.debug("easybank-correlationId found: {}", correlationId);
// 로직 생략
}
accounts
마이크로서비스에서 loans
및 cards
마이크로서비스로 요청을 전달할 때, 상관 관계 ID를 함께 전달하도록 FeignClient
인터페이스를 수정했습니다.LoansFeignClient
와 CardsFeignClient
에서 @RequestHeader
를 추가하여 상관 관계 ID를 수락합니다:@GetMapping("/api/fetch")
LoanDetails fetchLoanDetails(@RequestHeader(value = "easybank-correlationId", required = false) String correlationId, @RequestParam String mobileNumber);
application.yml
파일에 logging.level
을 추가하여 디버그 로깅을 활성화했습니다. 이를 통해 com.eazybytes
패키지의 모든 디버그 로그를 확인할 수 있습니다.accounts
, loans
, cards
)의 application.yml
에서 해당 설정을 추가했습니다:logging:
level:
com.eazybytes: debug
fetchCustomerDetails
API를 호출하여 상관 관계 ID가 모든 마이크로서비스로 전달되고 로그에 기록되는지 확인합니다.이번 챕터를 통해 상관 관계 ID를 활용하여 Gateway 서버를 통해 전달된 요청이 마이크로서비스 간에 어떻게 추적되고 로깅될 수 있는지 이해할 수 있었습니다. 이로 인해 시스템의 디버깅 및 문제 해결이 훨씬 쉬워졌습니다.
더욱 복잡한 비즈니스 로직과 크로스커팅 관심사를 처리할 수 있는 Gateway 서버의 유연성을 활용하여 더 안전하고 확장 가능한 마이크로서비스 아키텍처를 구축할 수 있습니다.