- Client와 Backend Server 사이의 출입문(Front Door)
- 라우팅(라우팅, API 변환, 서비스 프록시 ...)
- Filter
- cross-service concerns
- authentication, authorization
- rate limiting
- logging
- proxy
- metering (호출 통계 등)
- Micro Proxy
- 50개 이상의 AWS ELB 앞단에 위치해 3개의 AWS region에 걸쳐 하루 수백억 이상의 request를 처리
1. Zuul의 모든 요청은 HystrixCommand로 wrapping
- 각 API 경로(서버군) 별로 Circuit Breaker 생성
- 하나의 서버군에 장애가 발생해도 다른 서버군에는 영향이 없다.
- Circuit Breaker / ThreadPool의 다양한 속성을 통해 서비스 별 설정이 가능하다.
2. Zuul에는 Ribbon이 내장되어 있어 API를 전달할 서버의 목록을 갖고 Ribbon을 통해 LB를 수행한다.
- 주어진 서버 목록을 Round-Robin으로 호출
- Coding을 통해 LB 방식 커스텀 가능
3. Zuul에는 Eureka Client가 내장되어 있어 Eureka Client를 사용해 URL의 호출을 전달할 서버 리스트를 찾는다
- 각 URL에 Mapping된 서비스명을 찾아 Eureka Server를 통해 목록을 조회
- 조회된 서버 목록을 Ribbon에게 전달한다.
4. Eureka + Ribbon에 의해 결정된 Server address로 HTTP 요청
- Apache Http Client가 default
5. 선택된 서버로의 호출이 실패하면 Ribbon에 의해 자동으로 Retry
- Retry 수행 조건
- Http Client에서 Exception 발생 (IOException)
- 설정된 HTTP 응답코드 return
request가 zuul에 유입되면
- pre-filter 호출
- route-filter 호출
요청을 리다이렉션 할 수 있지만 기존 HTTP 요청을 종료한 후, 다시 자체적으로 경로를 호출하는 것이기 때문에 HTTP 리다이렉션은 아니다.
- post-filter 호출
- Zuul의 모든 호출은 HystrixCommand로 수행되어 Circuit Breaker를 통해 장애 시 fail fast 및 fallback 수행 가능
- Ribbon + Eureka를 통해 현재 서비스 가능한 서버 목록을 자동으로 갱신
- Ribbon의 retry를 통해 동일한 서버군으로의 자동 retry 가능
compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.retry:spring-retry')
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ApiGwApplication {
public static public static void main(String[] args) {
SpringApplication.run(ApiGwApplication.class, args);
}
}
- spring cloud zuul의 기본 isolation은 semaphore (netflix zuul은 threadpool)
semaphore는 network timeout을 격리하지 못한다.
그리고 tomcat thread가 200개여도 semaphore가 5개라면 5개 밖에 수행하지 못한다. - isolation을 thread로 변경
zuul.ribbon-isolation-strategy: thread
- allowMaximumSizeToDivergeFromCoreSize를 true로 설정해야만 maximumSize가 의미가 있다.
spring:
application:
name: apigw
server:
port: 8765
zuul:
ribbon-isolation-strategy: thread
thread-pool:
use-seperate-thread-pools: true
thread-pool-key-prefix: zuul-
routes:
home:
path: /home/**
serviceId: home
stripPrefix: false
external:
path: /external/**
serviceId: external
stripPrefix: false
eureka:
instance:
non-secure-port: ${server.port}
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:8761/eureka
hystrix:
threadpool:
zuul-home:
coreSize: 50
maximumSize: 100
allowMaximumSizeToDivergeFromCoreSize: true
zuul-external:
coreSize: 50
maximumSize: 100
allowMaximumSizeToDivergeFromCoreSize: true