반응형
Spring Cloud Gateway?
- MSA 환경에서 사용하는 API Gateway중 하나이다
- API 라우팅, 보안, 모니터링, 메트릭 등의 기능을 간단하고 효과적인 방법으로 제공한다
- Eureka는 로드 밸런스, Gateway는 라우팅에 초점을 둔 방식이다
API Gateway를 사용하는 이유?
- 유입되는 모든 요청/응답이 통하기 때문에 인증/보안을 적용하기 좋다
- URI 따라 서비스 엔드 포인트를 다르게 처리하는 동적 라우팅이 가능해진다
- 모든 트래픽이 통하기 때문에 모니터링 시스템 구성이 단순해진다
- 동적 라우팅이 가능하므로 신규 스펙을 서비스 일부에만 적용시키거나 트래픽을 점진적으로 늘려가는 테스트를 수행하기 수월해진다
Spring Cloud Gateway / Spring Cloud Zuul 차이점
- Spring Cloud Gateway
- 스프링에서 개발
- 비동기, 논블로킹 방식으로 처리한다
- 스프링 기반이기 때문에 스프링에서 사용하기 좋다
- 성능이 Zuul보다 좋다는 분석이 있다
- Netty 런타임 기반으로 서블릿 컨테이너나 WAR로 빌드된 경우 동작하지 않는다
- Spring Cloud Zuul
- 넷플릭스에서 개발
- 서블릿 프레임워크 기반으로 개발되어 동기, 블로킹 방식으로 처리
- Zuul2가 나오면서 비동기, 논블로킹 방식으로도 처리 가능하다
Spring Cloud Gateway 프로젝트 설정하기
pom.xml<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-msa-api-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-msa-api-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
application.yml
server:
port: 8080
---
spring:
cloud:
gateway:
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
# - id: cafe-api
# uri: http://localhost:8082/
# predicates:
# - Path=/api/cafe/**
user-api 서버에 컨트롤러 추가
- port : 8081
@Slf4j
@RestController
public class UserController {
@PostMapping("/api/user/login")
public String login(
@RequestHeader(required = false) Map<String, Object> headers,
@RequestPart(required = false) Map<String, Object> params,
@RequestBody(required = false) String body
) {
log.info("{}, {}, {}", headers, params, body);
return "Hello";
}
}
gateway를 통해 user-api 서버 호출
###
POST http://localhost:8080/api/user/login
Content-Type: application/json
{
"name": "john"
}
Hello
CustomFilter 추가하기
@Slf4j
@Component
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
public CustomFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
log.info("CustomFilter baseMessage>>>>>>" + config.getBaseMessage());
if (config.isPreLogger()) {
log.info("CustomFilter Start>>>>>>" + exchange.getRequest());
}
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
if (config.isPostLogger()) {
log.info("CustomFilter End>>>>>>" + exchange.getResponse());
}
}));
});
}
@Data
public static class Config {
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
}
spring:
cloud:
gateway:
default-filters:
- name: CustomFilter # 글로벌 설정
args:
baseMessage: Spring Cloud Gateway CustomFilter1
preLogger: true
postLogger: true
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
filters:
- name: CustomFilter # 개별 설정
args:
baseMessage: Spring Cloud Gateway CustomFilter2
preLogger: true
postLogger: true
After
- 특정 시간 이후부터 라우팅 처리 (ex. 특정 시간부터 서비스할 이벤트 API)
spring:
cloud:
gateway:
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
- After=2020-12-15T23:14:00.000+09:00[Asia/Seoul]
Before
- 특정 시간 이후부터 라우팅 처리하지 않음 (ex. Deprecated API)
spring:
cloud:
gateway:
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
- Before=2020-12-15T23:14:00.000+09:00[Asia/Seoul]
Between
- 특정 시간 사이에만 라우팅 처리 (ex. 특정 시간에만 받을 투표 API)
spring:
cloud:
gateway:
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
- Between=2020-12-01T00:00:00.000+09:00[Asia/Seoul], 2020-12-31T00:00:00.000+09:00[Asia/Seoul]
Weight
spring:
cloud:
gateway:
routes:
- id: user-api-1
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
- Weight=group-user-api, 7
- id: user-api-2
uri: http://localhost:8082/
predicates:
- Path=/api/user/**
- Weight=group-user-api, 3
RewritePath
- gateway의 /api/user/login으로 요청하면 user-api의 /api/login으로 라우팅
spring:
cloud:
gateway:
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
filters:
- RewritePath=/api/user/(?<path>.*),/api/$\{path}
Retry
spring:
cloud:
gateway:
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
filters:
- name: Retry
args:
retries: 3 # 재시도 횟수
statuses: INTERNAL_SERVER_ERROR # 재시도해야하는 HTTP 상태 (org.springframework.http.HttpStatus)
methods: GET # 재시도해야하는 HTTP 메소드 (org.springframework.http.HttpMethod)
backoff: # 재시도하는 시간텀 지정
firstBackoff: 1000ms
maxBackoff: 6000ms
factor: 2
basedOnPreviousValue: false
Timeout
spring:
cloud:
gateway:
httpclient:
connect-timeout: 10000 # 10초
response-timeout: 10s # 10초, 글로벌 설정시 seconds
routes:
- id: user-api
uri: http://localhost:8081/
predicates:
- Path=/api/user/**
metadata:
connect-timeout: 15000 # 15초
response-timeout: 15000 # 15초, 개별 설정시 milliseconds
Eureka Load Balance 요청
의존성 추가<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
API Gateway를 EurekaClient로 등록하도록 활성화
@EnableEurekaClient
@SpringBootApplication
public class SpringMsaGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMsaGatewayApplication.class, args);
}
}
application.yml
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URL:http://localhost:8787/eureka/} # 유레카 서버 설정
spring:
cloud:
gateway:
routes:
- id: user-api
# uri: http://localhost:8081/ # 기본 방식
uri: lb://user-api # 유레카를 통한 방식
predicates:
- Path=/api/user/**
참고
반응형
'Development > Spring' 카테고리의 다른 글
[Spring] H2 Database (0) | 2021.02.27 |
---|---|
[Spring] Spring Cloud Feign (0) | 2020.12.27 |
[Spring] Spring Cloud Hystrix (0) | 2020.12.27 |
[Spring] Spring Cloud Eureka (0) | 2020.12.27 |
[Spring] Spring Cloud Config (0) | 2020.12.27 |