본문 바로가기
Back-end/Spring Cloud (MSA)

Spring Cloud (MSA) API Gateway - 경로탐색(Exploring Routes), Logging Filter

by javapp 자바앱 2022. 12. 3.
728x90

 

이전 포스팅 : 로드밸런서

Spring Cloud Gateway 사용

  • Simple, yet effective way to route to APIs
  • Provide cross cutting concerns:
    • Security
    • Monitoring/metrics
  • Built on top of Spring WebFlux (Reactive Approach)
  • Features:
    • Match routes on any request attribute
    • Define Predicates and Filters
    • Integrates with Spring Cloud Discovery Client (Load Balancing)
    • Path Rewriting

 

 


 

 

Eureka
http://localhost:8761

 

 

Setting up Spring Cloud API Gateway

 

Dependencies

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

 

Gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.6'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.javapp'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

ext {
	set('springCloudVersion', "2021.0.5")
}

dependencies {
	implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
	implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

tasks.named('test') {
	useJUnitPlatform()
}

 

 

Register the application in Eureka by specifying the Eureka URL(File Name: application.properties)

spring.application.name=api-gateway
server.port=8765

# 유레카 서버 등록
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka

spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
  • 유레카 서버 등록

 

# 호환 가능한 서비스 레지스트리에 등록된 서비스를 기반으로 경로를 만들도록 구성
spring.cloud.gateway.discovery.locator.enabled=true

# 경로를 소문자로 설정
spring.cloud.gateway.discovery.locator.lower-case-service-id=true

 

 

 

URL 요청

localhost:API-gateway 포트/api-gateway 경로/서비스url

http://localhost:8765/currency-conversion/currency-conversion-feign/from/EUR/to/INR/quantity/10

 

API GATEWAY

http://localhost:8765/currency-conversion-feign/from/USD/to/INR/quantity/10
http://localhost:8765/currency-exchange/from/USD/to/INR/

 

유레카

http://localhost:8761

 

Currency Conversion Service

http://localhost:8100/currency-conversion-feign/from/USD/to/INR/quantity/10

 

Currency Exchange Service

http://localhost:8000/currency-exchange/from/USD/to/INR

 


 

 

Exploring Routes

@Configuration
public class ApiGatewayConfiguration
{
    @Bean
    public RouteLocator gatewayRouter(RouteLocatorBuilder builder)
    {

        return builder.routes()
                .route(p -> p.path("/get")
                        .filters(f ->
                                f.addRequestHeader("MyHeader","MyURI")
                                .addRequestParameter("param", "MyValue"))
                        .uri("http://httpbin.org:80"))
                .route(p->p.path("/currency-conversion-feign/**")
                        .uri("lb://currency-conversion"))
                .route(p->p.path("/currency-conversion-new/**")
                        .filters(f->f.rewritePath(
                                "/currency-conversion-new/(?<segment>.*)",
                                "/currency-conversion-feign/${segment}"
                        ))
                        .uri("lb://currency-conversion"))
                .build();
    }
}

 

 

헤더 추가와 파라미터 추가 

.route(p -> p.path("/get")
        .filters(f ->
                f.addRequestHeader("MyHeader","MyURI")
                .addRequestParameter("param", "MyValue"))
        .uri("http://httpbin.org:80"))

 

 

경로 축소

.route(p->p.path("/currency-conversion-feign/**")
        .uri("lb://currency-conversion"))

http://localhost:8765/currency-conversion/currency-conversion-feign/from/EUR/to/INR/quantity/10
--> http://localhost:8765/currency-conversion-feign/from/EUR/to/INR/quantity/10

 

"lb://{spring.application.name}" : 로드밸런싱으로 포트번호가 바뀌어도 API-Gateway는 해당 uri로 라우팅

스프링에서 유레카 서버를 통해 서버명을 확인한다.

 

 

경로 우회

.route(p->p.path("/currency-conversion-new/**")
        .filters(f->f.rewritePath(
                "/currency-conversion-new/(?<segment>.*)",
                "/currency-conversion-feign/${segment}"
        ))
        .uri("lb://currency-conversion"))

 


 

application.yml

server:
  port: 8765

management:
  endpoints:
    web:
      exposure:
        include:
          - "gateway"
  endpoint:
    gateway:
      enabled: true

spring:
  application:
    name: api-gateway

  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:
            - RewritePath=/user/(?<path>.*),/$\{path}


  # 유레카 서버 등록
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka

 

 

 


 

 

Logging Filter

package com.javapp.microservices.apigateway.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class LoggingFilter implements GlobalFilter {

    private Logger logger = LoggerFactory.getLogger(LoggingFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("URI 요청 받음 -> {}", exchange.getRequest().getPath());
        return chain.filter(exchange);
    }
}

 

 

리소스 요청시 필터를 통해 로그 확인

2022-12-02 14:34:08.406  INFO 9908 --- [ctor-http-nio-3] c.j.m.apigateway.log.LoggingFilter     : 
URI 요청 받음 -> /currency-conversion-feign/from/EUR/to/INR/quantity/10%0A

 

 

 

 

 

 

참고

Spring Cloud Gateway - Yun Blog | 기술 블로그 (cheese10yun.github.io)

 

 

댓글