Exploration de la nouvelle passerelle cloud Spring

Explorer la nouvelle passerelle Spring Cloud

1. Vue d'ensemble

Dans cet article, nous allons explorer les principales fonctionnalités du projetSpring Cloud Gateway, une nouvelle API basée sur Spring 5, Spring Boot 2 et Project Reactor.

L'outil fournit des mécanismes de routage prêts à l'emploi souvent utilisés dans les applications de microservices afin de masquer plusieurs services derrière une seule façade.

Pour une explication du modèle de passerelle sans le projet Spring Cloud Gateway, consultez nosprevious article.

2. Gestionnaire de routage

Se concentrant sur les demandes de routage, Spring Cloud Gateway transmet les demandes à un mappage de gestionnaire de passerelle, qui détermine ce qu'il convient de faire avec les demandes correspondant à un itinéraire spécifique.

Commençons par un exemple rapide de la façon dont le gestionnaire de passerelle résout les configurations d'itinéraire à l'aide deRouteLocator:

@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();
}

Remarquez comment nous avons utilisé les principaux blocs de construction de cette API:

  • Route – l'API principale de la passerelle. Il est défini par une identification (ID) donnée, une destination (URI) et un ensemble de prédicats et de filtres

  • Predicate – unPredicate – de Java 8 utilisé pour faire correspondre les requêtes HTTP à l'aide d'en-têtes, de méthodes ou de paramètres

  • Filter – un ressort standardWebFilter

3. Routage dynamique

Tout commeZuul, Spring Cloud Gateway fournit des moyens de routage des requêtes vers différents services.

La configuration de routage peut être créée en utilisant pur Java (RouteLocator, comme indiqué dans l'exemple de la section 2.1) ou en utilisant la configuration des propriétés:

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

4. Usines de routage

Spring Cloud Gateway fait correspondre les routes à l'aide de l'infrastructure Spring WebFluxHandlerMapping.

Il comprend également de nombreuses usines de prédicats de route intégrées. Tous ces prédicats correspondent à différents attributs de la requête HTTP. Les usines de prédicats de route multiples peuvent être combinées via le «et» logique.

La correspondance de route peut être appliquée par programme ou via un fichier de propriétés de configuration en utilisant un type différent de fabriques de prédicats de route.

4.1. Usine de prédicat de routeBefore

L'usine de prédicat de routeBefore prend un paramètre: adatetime. Ce prédicat correspond aux demandes qui se produisent avant ledatetime actuel:

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

La configuration Java peut être représentée comme suit:

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

4.2. Entre l'usine de prédicat d'itinéraire

L'usine de prédicat de routeBetween prend deux paramètres:datetime1, etdatetime2. Ce prédicat correspond aux demandes qui se produisent aprèsdatetime1 (inclus) et avantdatetime2 (exclusif). Le paramètredatetime2 doit être aprè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]

Et la configuration Java ressemble à ceci:

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. Usine de prédicat de routeHeader

L'usine de prédicat de routeHeader prend deux paramètres: le nom de l'en-tête et une expression régulière. Ce prédicat correspond à un en-tête correspondant à l'expression régulière:

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

La configuration Java peut être représentée comme suit:

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

4.4. Host Facteur de prédicat d'itinéraire

LaHost Route Predicate Factory prend un paramètre: le modèle de nom d'hôte. Le motif est un motif de style fourmi avec “.” Comme séparateur.

Ce prédicat correspond à l'en-têteHost avec le modèle donné:

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

Voici l'alternative de configuration Java:

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

4.5. Usine de prédicat de routeMethod

LaMethod Route Predicate Factory prend un paramètre: la méthode HTTP à faire correspondre:

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

La configuration Java peut être représentée comme suit:

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

4.6. Usine de prédicat de routePath

L'usine de prédicat de routePath prend un paramètre: un modèle SpringPathMatcher:

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

La configuration Java:

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

4.7. Usine de prédicat de routeQuery

LaQuery Route Predicate Factory prend deux paramètres: un paramètre obligatoire et une expression rationnelle facultative:

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

Et la configuration Java:

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

4.8. Usine de prédicat de routeRemoteAddr

LaRemoteAddr Route Predicate Factory prend une liste (minimum de 1) de chaînes de notation CIDR, par exemple,192.168.0.1/16 (où 192.168.0.1 est une adresse IP et 16 est un masque de sous-réseau):

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

Et la configuration Java correspondante:

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

5. Usines WebFilter

Les filtres de route permettent la modification de la requête HTTP entrante ou de la réponse HTTP sortante.

Spring Cloud Gateway inclut de nombreuses usines WebFilter intégrées.

5.1. AddRequestHeaderWebFilter Usine

Le WebFilter Factory deAddRequestHeader prend un paramètre de nom et de valeur:

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

Voici la configuration Java correspondante:

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

5.2. Usine WebFilterAddRequestParameter

Le WebFilter Factory deAddRequestParameter prend un paramètre de nom et de valeur:

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

La configuration Java correspondante:

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

5.3. Usine WebFilterAddResponseHeader

Le WebFilter Factory deAddResponseHeader prend un paramètre de nom et de valeur:

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

La configuration Java correspondante:

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

5.4. DisjoncteurWebFilter Usine

Hystrix est utilisé comme Circuit-Breaker WebFilter Factory et prend un seul paramètre de nom, qui est le nom de la commande Hystrix:

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

La configuration Java correspondante:

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

Usine WebFilter5.5. RedirectTo

La WebFilter Factory deRedirectTo prend un statut et un paramètre URL. Le statut doit être un code HTTP 300 de redirection, tel que 301:

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

Et la configuration Java correspondante:

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

5.6. Usine WebFilterRewritePath

La WebFilter Factory deRewritePath prend un paramètre de regexp de chemin et un paramètre de remplacement. Ceci utilise des expressions régulières Java pour réécrire le chemin de requête.

Voici un exemple de configuration:

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

La configuration Java peut être représentée comme suit:

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

5.7. Usine WebFilterRequestRateLimiter

RequestRateLimiter WebFilter Factory prend trois paramètres:replenishRate, capacity, etkeyResolverName.

  • replenishRate représente le nombre de requêtes par seconde que vous voulez qu'un utilisateur soit autorisé à faire

  • capacity définit la capacité de rafale autorisée

  • keyResolverName - est le nom d'un bean qui implémente l'interfaceKeyResolver

L'interface KeyResolver permet aux stratégies enfichables de dériver la clé pour limiter les demandes:

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

La configuration Java peut être représentée comme suit:

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

6. Prise en charge de Spring Cloud DiscoveryClient

Spring Cloud Gateway peut être facilement intégré aux bibliothèques Service Discovery et Registry, telles que Eureka Server et Consul:

@Configuration
@EnableDiscoveryClient
public class GatewayDiscoveryConfiguration {

    @Bean
    public DiscoveryClientRouteDefinitionLocator
      discoveryClientRouteLocator(DiscoveryClient discoveryClient) {

        return new DiscoveryClientRouteDefinitionLocator(discoveryClient);
    }
}

6.1. FiltreLoadBalancerClient

LeLoadBalancerClientFilter recherche un URI dans la propriété d'attribut d'échange en utilisantServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR.

Si l'URL a un schémalb (par exemple,lb://example-service), elle utilisera Spring CloudLoadBalancerClient pour résoudre le nom(i.e., example-service) en un hôte et un port réels.

L'URL d'origine non modifiée est placée dans l'attributServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR.

7. surveillance

Spring Cloud Gateway utilise l’API Actuator, une bibliothèque bien connue de Spring-Boot, qui fournit plusieurs services prêts à l’emploi pour la surveillance de l’application.

Une fois l'API de l'actionneur installée et configurée, les fonctionnalités de surveillance de la passerelle peuvent être visualisées en accédant au point de terminaison/gateway/.

8. la mise en oeuvre

Nous allons maintenant créer un exemple simple d'utilisation de Spring Cloud Gateway en tant que serveur proxy à l'aide du prédicatpath.

8.1. Les dépendances

Spring Cloud Gateway se trouve actuellement dans le référentiel des jalons, sur la version 2.0.0.RC2. C'est également la version que nous utilisons ici.

Pour ajouter le projet, nous utiliserons le système de gestion des dépendances:


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

Ensuite, nous ajouterons les dépendances nécessaires:


    org.springframework.boot
    spring-boot-actuator


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


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

8.2. Implémentation du code

Et maintenant, nous créons une configuration de routage simple dans le fichierapplication.yml:

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

Et le code de l'application Gateway:

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

Après le démarrage de l'application, nous pouvons accéder à l'url:“http://localhost/actuator/gateway/routes/example_route” pour vérifier toute la configuration de routage créée:

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

Nous voyons que l'url relative:“/example” est configurée comme une route, ** donc en frappant l'url“http://localhost/example”, nous serons redirigés vers «http://example.com», comme cela a été configuré dans notre exemple.

9. Conclusion

Dans cet article, nous avons exploré certaines des fonctionnalités et des composants de Spring Cloud Gateway. Cette nouvelle API fournit des outils prêts à l'emploi pour la prise en charge des passerelles et des mandataires.

Les exemples présentés ici se trouvent dans nosGitHub repository.