Rental Application (React & Spring boot Microservice) - 3 : APIGATEWAY-SERVICE

yellow_note·2021년 8월 16일
0

#1 Spring Cloud gateway

Spring Cloud Gateway는 하나의 api gateway server를 만들어 클라이언트의 요청을 해당 게이트웨이 서버로 보내고 조건에 따라 이 요청에 해당하는 서비스에 요청을 전달해주는 역할을 합니다.

#2 프로젝트 구현

Rental Application에서는 이 api gateway의 포트를 8900번으로 설정하고 진행하도록 하겠습니다.

#3 Custom Filter

1) client의 요청을 받고 Gateway Handler Mapping은 Predicates에서 경로와 일치하는지 판단합니다.

2) Gateway Web Handler는 필터 옵션에 명시한 클래스와 같은 설정들을 이용하여 요청을 전송합니다.

3) 필터들은 Pre, Post로 나누어 요청과 응답을 처리합니다.

package com.microservices.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);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // Pre Filter
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();

            log.info("PRE Filter: request Id -> {}", request.getId());

            // Post Filter
            return chain.filter(exchange)
                        .then(Mono.fromRunnable(() -> {
                            log.info("POST Filter: response code -> {}", 	response.getStatusCode());
                        }));
        };
    }

    public static class Config {
        // Configuration properties
    }
}

Global Filter

이제 이 CustomFilter를 바탕으로 하여 GlobalFilter를 만들어 기본 필터로써 사용하도록 하겠습니다.

application.yml처럼 gateway: 다음 들여쓰기로 default-filters.name에 GlobalFilter클래스명을, 그 아래 args에는 GlobalFilter 클래스 Config클래스에 명시한 변수에 대한 설정값들을 명시하도록 합니다.

package com.microservices.filter;

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);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // 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());
            }

            // Post Filter
            return chain.filter(exchange)
                        .then(Mono.fromRunnable(() -> {
                            if(config.isPostLogger()) {
                                log.info("Global Filter End: response code -> {}", response.getStatusCode());
                            }
                        }));
        };
    }

    @Data
    public static class Config {
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }
}

Logging Filter

Logging Filter의 주 목적은 요청이 들어왔을 때 어떤 uri값을 타고 들어왔는지 로그에 대한 값을 추적하기 위함입니다. 이 필터도 마찬가지로 CustomFilter를 기반으로 작성하도록 하겠습니다.

package com.microservices.filter;

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);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // 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());
            }

            // Post Filter
            return chain.filter(exchange)
                        .then(Mono.fromRunnable(() -> {
                            if(config.isPostLogger()) {
                                log.info("Global Filter End: response code -> {}", response.getStatusCode());
                            }
                        }));
        };
    }

    @Data
    public static class Config {
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }
}

참고

인프런: Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA) - 이도원

다음 포스트는 Auth-Service를 구현하면서 Gateway의 필터값들이 어떤 값으로 들어오는지 확인하도록 하겠습니다.

0개의 댓글