MOA -> MSA로 전환 되면서 하나의 큰 서버에서 작은 여러개의 서버로 나눠졌다.
클라이언트 입장에서는 각 서버들의 주소를 모두 알고 있기는 어렵다.
그래서 Gateway서버가 필요해 졌다.
Gateway서버는 말그대로 입구이다. 클라이언트는 gateway 서버 주소만 알고 있으면 모든 서비스에 접근이 가능하다. 클라이언트 입장에서는 모놀리틱 서비스와 크게 다르지 않게 느낄 수 있다. 또한 각 서버들을 노출하지 않으므로 보안에도 이점이 있다.
spring cloud gateway는 비동기 was 인 netty를 사용한다.
멀티모듈로 gateway모듈을 추가 했다.
의존성 추가
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
application.yml
eureka:
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
hostname: localhost
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka
server:
port: 9000 #포트
spring:
application:
name: gateway-service #서버 이름
cloud:
gateway:
routes:
- id: api-service
uri: lb://API-SERVICE
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>.*), /$\{segment}
- id: auth-service
uri: lb://AUTH-SERVICE
predicates:
- Path=/auth/**
filters:
- RewritePath=/auth/(?<segment>.*), /$\{segment}
옵션 | 설명 |
---|---|
id | 라우터 id |
url | 해당서버(유레카에 등록한 서버이름)로 라우팅 한다는 의미(lb는 로드밸런서 사용) |
predicates | 해당 path로 요청이 들어올 경우 라우팅 |
filters | 라우팅 하기전 필터를 추가 |
RewritePath=/api/(?<segment>.*), /$\{segment}
/api/test 로 요청이 들어올 경우 /api/를 빼고 /test 만 전달
로드밸런서는 기본적으로 라운드 로빈을 사용한다.
필터 등록하는 방법을 알아보자.
@Component
@Slf4j
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config> {
// 설정 객체 주입
public GlobalFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// http request, response
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("{}", config.getMessage());
log.info("Global filter Start: request id -> {}", request.getId());
log.info("Global request getURI -> {}", request.getURI());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("Global filter End: response code -> {}", response.getStatusCode());
}));
};
}
@Data
public static class Config {
private String message; // 해당 필드들은 application.yml 파일에서 주입
}
}
application.yml
spring:
...
cloud:
gateway:
default-filters: # 글로벌 필터의 경우 여기에 위치한다.
- name: GlobalFilter # 생성한 필터 클래스명
args:
message: Gateway Global Filter!! # 필터안 설정 객체에 바인딩
routes:
- id: test
uri: lb://API-SERVICE
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>.*), /$\{segment}
- name: AuthFilter # 각 서버별로 필터를 적용할 경우 여기에 추가
args:
token: test
http://localhost:9000/api/health_check