관리 메뉴

너와 나의 스토리

Spring Cloud: Spring Cloud Gateway를 edge server로 사용 본문

개발

Spring Cloud: Spring Cloud Gateway를 edge server로 사용

노는게제일좋아! 2022. 4. 6. 21:42
반응형

에지 서버

  • 사설 서비스를 외부에서 접근하지 못하도록 숨기고 외부 클라이언트가 공개 서비스를 사용할 때 보호한다.
  • 처음에 스프링 클라우드는 넷플릭스 zuul v1을 에지 서버로 사용했으나, 스프링 클라우드 그리니치가 출시된 이후로는 spring cloud gateway로 대체하는 것을 권장한다.

 

  Netflix Zuul 1 Spring Cloud Gateway
차이점 - blocking API 사용 - Spring 5, project reactor, spring bot 2 기반의 non-blocking API 사용
특징 Spring boot 2.3까지만 지원 -zuul에 비해 더 많은 양의 동시 요청을 처리할 수 있으며, 이는 모든 외부 트래픽을 처리해야 하는 에지 서버에게는 중요한 특성이다.

 

1. Dependency

    •  'spring-cloud-gateway' dependency 추가
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'

 

2. Routing

  • 특정 uri로 들어오는 요청을 라우팅
  • 라우팅 방법:
    1. Configuration을 통한 라우팅
    2. application.yml을 통한 라우팅

 

1. configuration을 통한 라우팅 방법

  • path: regex가 "/first/**"인 형식으로 요청이 들어오면 -> predicate
  • filters: 해당 요청 부분을 "/first/a"로 바꿔서 다시 요청한다. 
  • uri: 라우팅할 uri 또한 지정할 수 있다.
  • controller에 존재하는 url로 접근하면  바로 그 url로 요청이 향하게 되고, 그 이외의 요청 중 아래의 RouteLocatorConfig에 명시한 predicate(조건부)에 부합한 요청이 오면 라우팅된다.
@Configuration
public class RouteLocatorConfig {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {

        ApiType type = new ApiType();

        return builder
                .routes()
                .route(r -> r.path("/first/**")
                        .filters((f-> f.rewritePath("/.*","/first/a")))
                        .uri("http://localhost:8080"))
                .build();
    }
}
  • request url을 받아서 파싱해서 라우팅할 url을 만들 수 있다.
    • regex 또한 또다른 클래스에 정의해서 사용할 수 있다.
    • 예: 사용자가 "http://localhost:8080/second/10"로 요청하면, 여기서 id 값인 10을 파싱해서 routed uri에 id를 더해 새로운 url을 만들어 라우팅한다.
public class ApiType {

    private final String regex;

    public ApiType() {
        this.regex = "/second/*";
    }

    public String regex() {
        return regex;
    }

    public String routedHost(RequestPath path) {
        return "/second/specific/path" + getId(path.toString());
    }

    private String getId(String path) {
        return path.substring(path.lastIndexOf("/" + 1)).trim();
    }
}


@Configuration
public class RouteLocatorConfig {

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder) {

        ApiType type = new ApiType();

        return builder
                .routes()
                .route(r -> r.path(type.regex())
                        .filters(f -> f.changeRequestUri(e -> Optional.of(URI.create("http://localhost:8080" +type.routedHost(e.getRequest().getPath())))))
                        .uri("http://localhost:8080"))
                .build();
    }
}

 

 

2. application.yml을 사용한 라우팅 방법

  • 다음과 같은 설정을 application.yml에서 설정해보자.
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {

    ApiType type = new ApiType();

    return builder
            .routes()
            .route(r -> r.path("/first/**")
                    .filters((f-> f.rewritePath("/.*","/first/a")))
                    .uri("http://localhost:8080"))
            .route(r -> r.path("/second/**")
                    .filters((f-> f.rewritePath("/.*","/second/a")))
                    .uri("http://localhost:8080"))
            .build();
}
spring:
  main:
    web-application-type: reactive
  application:
    name: Scg
  cloud:
    gateway:
      routes:
        - id: first_service
          uri: http://localhost:8080
          predicates:
            - Path=/first/**
          filters:
            - SetPath=/first/a

        - id: second_service
          uri: http://localhost:8080
          predicates:
            - Path=/second/**
          filters:
            - SetPath=/second/a

 

3. Filtering

  • GlobalFilter: 모든 요청에 적용되는 필터
@Component
public class CustomFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // pre filter
        return chain.filter(exchange);
        // post filter
    }
}
  • 필터 순서를 지정할 수 있다.
    • Ordered를 implements
@Component
public class CustomSecondFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // pre filter
        return chain.filter(exchange);
        // post filter
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

 

 

 

 

참고

- 정규표현식: https://support.cognex.com/docs/vidi_341/web/KO/vidisuite/Content/ViDi_Topics/1_Overview/images_display_filters_regex_basics.htm

- https://cloud.spring.io/spring-cloud-gateway/reference/html/

- https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

반응형
Comments