Spring Cloud

5. zuul - [Spring Cloud를 활용한 MSA 기초 온라인 강의 실습]

Zuul - API Gateway

출처 - https://github.com/Netflix/zuul/wiki

API Gateway는 API의 요청자인 Client와 API의 제공자인 backend service를 연결하는 중계자(또는 출입문)

 

API Gateway가 필요한 이유

1. 횡단 관심사

- 인증/인가: 부적절한 요청을 차단하여 Backend service를 보호

- rate limiting: 일정량 이상의 요청 제한

- metering: 계측

- Logging: 유통되는 트래픽 로깅

- proxy

2. L/B & Routing: Client의 요청에 따라 적절한 backend service를 로드밸런싱(L/B: Load Balancing)하고 연결(라우팅)

3. Circuit Break: Backend service 장애 감지 및 대처

 

출처 - https://medium.com/netflix-techblog/announcing-zuul-edge-service-in-the-cloud-ab3af5be08ee

Zuul Filter는 크게 4가지 Filter로 나누어 진다.

  1. PRE Filter - 라우팅전에 실행되며 필터이다. 주로 logging, 인증등이 pre Filter에서 이루어 진다.
  2. ROUTING Filter - 요청에 대한 라우팅을 다루는 필터이다. Apache httpclient를 사용하여 정해진 Url로 보낼수 있고, Neflix Ribbon을 사용하여 동적으로 라우팅 할 수도 있다.
  3. POST Filter - 라우팅 후에 실행되는 필터이다. response에 HTTP header를 추가하거나, response에 대한 응답속도, Status Code, 등 응답에 대한 statistics and metrics을 수집한다.
  4. ERROR Filter - 에러 발생시 실행되는 필터이다.

 Zuul Components

zuul은 zuul-core, zuul-simple-webapp, zuul-netflix, zuul-netflix-webapp 4개의 컨포넌트로 구성한다.

  • zuul-core : 위에서 설명한 Zuul의 Request Lifecycle를 담당하고, Fliter를 컴파일하고 실행한는 기능을 담당하고 있는 Zuul의 core library
  • zuul-netflix : 기본적은 Zuul에 NetflixOSS library를 추가한다.
  • zuul-simple-webapp : zuul-core만 사용한 아주 기본적은 web application
  • zuul-netflix-webapp : zuul-core와 zuul-netflix를 함께 사용한 web application

API GATEWAY를 구축하기 위해서는 zuul-simple-webapp를 사용하다는 것은 MSA 환경에서 아주 유용한 NetflixOSS library를 포기하는 것이다. zuul-netflix-webapp을 도입하기에는 학습곡선이 크다. 그래서 찾은게 spring cloud netflix 프로젝트이다.

 

  • RouteLocator은 url path에 대한 routing을 지정한다. 요청이 들어오면 url path로 어떻게 routing 할 것인가를 정의하고 있다.
  • ZuulHandlerMapping은 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping을 상속받고, RouteLocator에 정의된 url path에 zuulController를 매핑한다. RouteLocator에 정의된 path의 요청이 들어오면 zuulController를 호출하게 된다.
  • ZuulController은 org.springframework.web.servlet.mvc.ServletWrappingController를 상속받으며, ZuulServlet을 주입시킨다. 그래서 ZuulController로 들어온 모든 요청은 ZuulServlet으로 처리한다.
  • ZuulFilterInitializer는 filter Map에 정의된 filter를 FilterRegistry에 등록하고, FilterLoader로 로딩한다.

Spring Cloud Zuul은 @EnableZuulProxy와 @EnableZuulServer 두 종류의 annotation으로 Zuul을 구동시킨다. 두개는 완전히 다른 것이 아니고 @EnableZuulProxy가 @EnableZuulServer을 포함한다. @EnableZuulServer에서 PreDecorationFilter, RibbonRoutingFilter, SimpleHostRoutingFilter를 추가하면, @EnableZuulProxy가 되는 것이다.

 

더 자세한 설명은 http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html

 

실습

1. 의존성 추가

ext['springCloudVersion'] = 'Finchley.SR2'

...

dependencies {
    compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
    compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

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

 

2. zuul, eureka 설정

spring:
  application:
    name: zuul

server:
  port: 8765

zuul:
  routes:
    product:
      path: /products/**
      serviceId: product
      stripPrefix: false
    display:
      path: /displays/**
      serviceId: display
      stripPrefix: false
  ribbon-isolation-strategy: thread
  thread-pool:
    use-separate-thread-pools: true
    thread-pool-key-prefix: zuul-

eureka:
  instance:
    non-secure-port: ${server.port}
    prefer-ip-address: true
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

 

3. config

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class, args);
    }
}

 

4. zuul에 hystrix, ribbon 설정해서 사용

compile('org.springframework.retry:spring-retry:1.2.2.RELEASE')
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
    product:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000
  threadpool:
    zuul-product:
      coreSize: 30
      maximumSize: 100
      allowMaximumSizeToDivergeFromCoreSize: true
    zuul-display:
      coreSize: 30
      maximumSize: 100
      allowMaximumSizeToDivergeFromCoreSize: true

product:
  ribbon:
    MaxAutoRetriesNextServer: 1
    ReadTimeout: 3000
    ConnectTimeout: 1000
    MaxTotalConnections: 300
    MaxConnectionsPerHost: 100

display:
  ribbon:
    MaxAutoRetriesNextServer: 1
    ReadTimeout: 3000
    ConnectTimeout: 1000
    MaxTotalConnections: 300
    MaxConnectionsPerHost: 100

Reference

https://www.youtube.com/watch?v=6g1wH97BiuQ&list=PL9mhQYIlKEhdtYdxxZ6hZeb0va2Gm17A5&index=8 https://woowabros.github.io/r&d/2017/06/13/apigateway.html