Explorando o novo Spring Cloud Gateway

Explorando o novo Spring Cloud Gateway

1. Visão geral

Neste artigo, exploraremos os principais recursos do projetoSpring Cloud Gateway, uma nova API baseada no Spring 5, Spring Boot 2 e Project Reactor.

A ferramenta fornece mecanismos de roteamento prontos para uso, geralmente usados ​​em aplicativos de microsserviços, como uma maneira de ocultar vários serviços atrás de uma única fachada.

Para obter uma explicação sobre o padrão de gateway sem o projeto Spring Cloud Gateway, verifique nossoprevious article.

2. Manipulador de roteamento

Sendo focado em solicitações de roteamento, o Spring Cloud Gateway encaminha solicitações para um Mapeador de Manipulador de Gateway - que determina o que deve ser feito com solicitações que correspondem a uma rota específica.

Vamos começar com um exemplo rápido de como o gerenciador de gateway resolve configurações de rota usandoRouteLocator:

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
      .route("r1", r -> r.host("**.example.com")
        .and()
        .path("/example")
        .uri("http://example.com"))
      .route(r -> r.host("**.example.com")
        .and()
        .path("/myOtherRouting")
        .filters(f -> f.prefixPath("/myPrefix"))
        .uri("http://othersite.com")
        .id("myOtherID"))
    .build();
}

Observe como usamos os principais blocos de construção dessa API:

  • Route – a API principal do gateway. É definido por uma determinada identificação (ID), um destino (URI) e um conjunto de predicados e filtros

  • Predicate – umPredicate – do Java 8 que é usado para atender solicitações HTTP usando cabeçalhos, métodos ou parâmetros

  • Filter – um Spring padrãoWebFilter

3. Roteamento Dinâmico

Assim comoZuul, o Spring Cloud Gateway fornece meios para rotear solicitações para serviços diferentes.

A configuração de roteamento pode ser criada usando Java puro (RouteLocator, conforme mostrado no exemplo na seção 2.1) ou usando configuração de propriedades:

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
      - id: example
        uri: example.com
      - id: myOtherRouting
        uri: localhost:9999

4. Fábricas de Roteamento

O Spring Cloud Gateway faz a correspondência de rotas usando a infraestrutura Spring WebFluxHandlerMapping.

Ele também inclui muitas fábricas de predicados de rota integradas. Todos esses predicados correspondem a atributos diferentes da solicitação HTTP. Várias fábricas de predicados de rota podem ser combinadas através do “e” lógico.

A correspondência de rota pode ser aplicada programaticamente ou por meio do arquivo de propriedades de configuração usando um tipo diferente de Route Predicate Factories.

4.1. Before Fábrica de Predicado de Rota

A fábrica de predicado de rotaBefore tem um parâmetro: adatetime. Este predicado corresponde às solicitações que acontecem antes dodatetime atual:

spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: http://example.com
        predicates:
        - Before=2017-09-11T17:42:47.789-07:00[America/Alaska]

A configuração Java pode ser representada como:

//..route definition
.route(r -> r.before(LocalDateTime.now().atZone(ZoneId.systemDefault()))
.id("before_route")
.uri("http://example.com")

4.2. Entre Fábrica de Predicado de Rota

A fábrica de predicado de rotaBetween assume dois parâmetros:datetime1,edatetime2. Este predicado corresponde às solicitações que acontecem depois dedatetime1 (inclusive) e antes dedatetime2 (exclusivo). O parâmetrodatetime2 deve estar apósdatetime1:

spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: http://example.com
        predicates:
        - Between=2017-09-10T17:42:47.789-07:00[America/Alaska], 2017-09-11T17:42:47.789-07:00[America/Alaska]

E a configuração do Java é assim:

ZonedDateTime datetime1 = LocalDateTime.now().minusDays(1).atZone(ZoneId.systemDefault());
ZonedDateTime datetime2 = LocalDateTime.now().atZone(ZoneId.systemDefault())
//..route definition
.route(r -> r.between(datetime1, datetime2))
.id("between_route")
.uri("http://example.com")

4.3. Header Fábrica de Predicado de Rota

O Route Predicate FactoryHeader usa dois parâmetros: o nome do cabeçalho e uma expressão regular. Esse predicado corresponde a um cabeçalho que corresponde à expressão regular:

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://example.com
        predicates:
        - Header=X-Request-Id, \d+

A configuração Java pode ser representada como:

//..route definition
.route(r -> r.header("X-Request-Id", "\\d+")
.id("header_route")
.uri("http://example.com")

4.4. Host fator predicado de rota

O Route Predicate FactoryHost tem um parâmetro: o padrão do nome do host. O padrão é um padrão no estilo Ant com "." como o separador.

Este predicado corresponde ao cabeçalhoHost com o padrão fornecido:

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: http://example.com
        predicates:
        - Host=**.example.com

Esta é a alternativa de configuração Java:

//..route definition
.route(r -> r.host("**.example.com")
.id("host_route")
.uri("http://example.com")

4.5. Method Fábrica de Predicado de Rota

O Route Predicate FactoryMethod usa um parâmetro: o método HTTP para corresponder:

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: http://example.com
        predicates:
        - Method=GET

A configuração Java pode ser representada como:

//..route definition
.route(r -> r.method("GET")
.id("method_route")
.uri("http://example.com")

4.6. Path Fábrica de Predicado de Rota

OPath Route Predicate Factory usa um parâmetro: um padrão SpringPathMatcher:

spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: http://example.com
        predicates:
        - Path=/articles/{articleId}

A configuração Java:

//..route definition
.route(r -> r.path("/articles/"+articleId)
.id("path_route")
.uri("http://example.com")

4.7. Query Fábrica de Predicado de Rota

OQuery Route Predicate Factory leva dois parâmetros: um parâmetro obrigatório e um regexp opcional:

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: http://example.com
        predicates:
        - Query=articleId, \w

E a configuração Java:

//..route definition
.route(r -> r.query("articleId", "\w")
.id("query_route")
.uri("http://example.com")

4.8. RemoteAddr Fábrica de Predicado de Rota

ORemoteAddr Route Predicate Factory leva uma lista (mínimo de 1) de strings de notação CIDR, por exemplo,192.168.0.1/16 (onde 192.168.0.1 é um endereço IP e 16 é uma máscara de sub-rede):

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: http://example.com
        predicates:
        - RemoteAddr=192.168.1.1/24

E a configuração Java correspondente:

//..route definition
.route(r -> r.remoteAddr("192.168.1.1/24")
.id("remoteaddr_route")
.uri("http://example.com")

5. Fábricas WebFilter

Os filtros de rota tornam possível a modificação da solicitação HTTP de entrada ou da resposta HTTP de saída.

O Spring Cloud Gateway inclui muitas fábricas WebFilter integradas.

5.1. AddRequestHeader Fábrica deWebFilter

OAddRequestHeader WebFilter Factory leva um parâmetro de nome e valor:

spring:
  cloud:
    gateway:
      routes:
      - id: addrequestheader_route
        uri: http://example.com
        predicates:
        - Path=/articles
        filters:
        - AddRequestHeader=X-SomeHeader, bael

Aqui está a configuração Java correspondente:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.addRequestHeader("X-TestHeader", "rewrite_request"))
  .uri("http://example.com")
  .id("addrequestheader_route")

5.2. AddRequestParameter WebFilter Factory

OAddRequestParameter WebFilter Factory leva um parâmetro de nome e valor:

spring:
  cloud:
    gateway:
      routes:
      - id: addrequestparameter_route
        uri: http://example.com
        predicates:
        - Path=/articles
        filters:
        - AddRequestParameter=foo, bar

A configuração Java correspondente:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.addRequestParameter("foo", "bar"))
  .uri("http://example.com")
  .id("addrequestparameter_route")

5.3. AddResponseHeader WebFilter Factory

OAddResponseHeader WebFilter Factory leva um parâmetro de nome e valor:

spring:
  cloud:
    gateway:
      routes:
      - id: addrequestheader_route
        uri: http://example.com
        predicates:
        - Path=/articles
        filters:
        - AddResponseHeader=X-SomeHeader, Bar

A configuração Java correspondente:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.addResponseHeader("X-SomeHeader", "Bar"))
  .uri("http://example.com")
  .id("addresponseheader_route")

5.4. DisjuntorWebFilter Fábrica

Hystrix é usado como WebFilter Factory do disjuntor e leva um único parâmetro de nome, que é o nome do comando Hystrix:

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: http://example.com
        predicates:
        - Path=/articles
        filters:
        - Hystrix=someCommand

A configuração Java correspondente:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.hystrix("some-command"))
  .uri("http://example.com")
  .id("hystrix_route")

5.5. RedirectTo WebFilter Factory

ORedirectTo WebFilter Factory assume um status e um parâmetro de URL. O status deve ser um código HTTP de redirecionamento 300, como 301:

spring:
  cloud:
    gateway:
      routes:
      - id: redirectto_route
        uri: http://example.com
        predicates:
        - Path=/articles
        filters:
        - RedirectTo=302, http://foo.bar

E a configuração Java correspondente:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.redirect("302","http://foo.bar"))
  .uri("http://example.com")
  .id("redirectto_route")

5.6. RewritePath WebFilter Factory

ORewritePath WebFilter Factory usa um parâmetro de expressão regular do caminho e um parâmetro de substituição. Isso usa expressões regulares do Java para reescrever o caminho da solicitação.

Aqui está um exemplo de configuração:

spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: http://example.com
        predicates:
        - Path=/articles/**
        filters:
        - RewritePath=/articles/(?.*), /$\{articleId}

A configuração Java pode ser representada como:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.rewritePath("(?.*)", articleId))
  .uri("http://example.com")
  .id("rewritepath_route")

5.7. RequestRateLimiter WebFilter Factory

O RequestRateLimiter WebFilter Factory usa três parâmetros:replenishRate, capacity,ekeyResolverName.

  • replenishRate representa quantas solicitações por segundo você deseja que um usuário tenha permissão para fazer

  • capacity define quanta capacidade de bursting seria permitida

  • keyResolverName - é o nome de um bean que implementa a interfaceKeyResolver

A interface KeyResolver permite que estratégias conectáveis ​​derivem a chave para limitar solicitações:

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: http://example.com
        predicates:
        - Path=/articles
        filters:
        - RequestRateLimiter=10, 50, userKeyResolver

A configuração Java pode ser representada como:

//...route definition
.route(r -> r.path("/articles")
  .filters(f -> f.requestRateLimiter().configure(c -> c.setRateLimiter(myRateLimiter)))
  .uri("http://example.com")
  .id("requestratelimiter_route")

6. Suporte Spring Cloud DiscoveryClient

O Spring Cloud Gateway pode ser facilmente integrado às bibliotecas Service Discovery e Registry, como Eureka Server e Consul:

@Configuration
@EnableDiscoveryClient
public class GatewayDiscoveryConfiguration {

    @Bean
    public DiscoveryClientRouteDefinitionLocator
      discoveryClientRouteLocator(DiscoveryClient discoveryClient) {

        return new DiscoveryClientRouteDefinitionLocator(discoveryClient);
    }
}

6.1. FiltroLoadBalancerClient

OLoadBalancerClientFilter procura um URI na propriedade do atributo de troca usandoServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR.

Se o URL tiver um esquemalb (por exemplo,lb://example-service), ele usará o Spring CloudLoadBalancerClient para resolver o nome(i.e., example-service) para um host e porta reais.

O URL original não modificado é colocado no atributoServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR.

7. Monitoramento

O Spring Cloud Gateway utiliza a API do atuador, uma conhecida biblioteca Spring-Boot que fornece vários serviços prontos para o monitoramento do aplicativo.

Depois que a API do atuador é instalada e configurada, os recursos de monitoramento do gateway podem ser visualizados acessando o endpoint/gateway/.

8. Implementação

Agora vamos criar um exemplo simples do uso do Spring Cloud Gateway como um servidor proxy usando o predicadopath.

8.1. Dependências

O Spring Cloud Gateway está atualmente no repositório de marcos, na versão 2.0.0.RC2. Esta também é a versão que estamos usando aqui.

Para adicionar o projeto, usaremos o sistema de gerenciamento de dependências:


    
        
            org.springframework.cloud
            spring-cloud-gateway
            2.0.0.RC2
            pom
            import
        
    

A seguir, adicionaremos as dependências necessárias:


    org.springframework.boot
    spring-boot-actuator


    org.springframework.boot
    spring-boot-starter-webflux


    org.springframework.cloud
    spring-cloud-starter-gateway

8.2. Implementação de código

E agora criamos uma configuração de roteamento simples no arquivoapplication.yml:

spring:
  cloud:
    gateway:
      routes:
      - id: example_route
        uri: http://example.com
        predicates:
        - Path=/example/
management:
  endpoints:
    web:
      exposure:
        include: "*'

E o código do aplicativo Gateway:

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

Depois que o aplicativo for iniciado, podemos acessar a url:“http://localhost/actuator/gateway/routes/example_route” para verificar todas as configurações de roteamento criadas:

{
    "id":"example_route",
    "predicates":[{
        "name":"Path",
        "args":{"_genkey_0":"/example"}
    }],
    "filters":[],
    "uri":"http://example.com",
    "order":0
}

Vemos que o url relativo:“/example” está configurado como uma rota, ** assim, ao acessar o url“http://localhost/example”, seremos redirecionados para “http://example.com“, conforme configurado em nosso exemplo

9. Conclusão

Neste artigo, exploramos alguns dos recursos e componentes que fazem parte do Spring Cloud Gateway. Essa nova API fornece ferramentas prontas para o uso para gateway e suporte a proxy.

Os exemplos apresentados aqui podem ser encontrados em nossoGitHub repository.