Notas - Spring Cloud (diez): Spring Cloud Gateway (enrutamiento)

Spring Cloud (diez): Spring Cloud Gateway (enrutamiento)

Este artículo presenta principalmente qué es Spring Cloud Gateway,

Inserte la descripción de la imagen aquí

Visión de conjunto

Spring Cloud Gateway es un nuevo proyecto de Spring Cloud. El proyecto es una puerta de enlace desarrollada en base a las tecnologías Spring 5.0, Spring Boot 2.0 y Project Reactor. Su objetivo es proporcionar un método de administración de enrutamiento API unificado simple y efectivo para la arquitectura de microservicios.

Como puerta de enlace en el ecosistema de Spring Cloud, Spring Cloud Gateway tiene como objetivo reemplazar Netflix Zuul. No solo proporciona un método de enrutamiento unificado, sino que también proporciona funciones básicas de la puerta de enlace basadas en la cadena de filtros, como: seguridad, monitoreo, enterramiento y limitación de corriente. Espere.

Características de Spring Cloud Gateway:

  • Basado en Spring Framework 5, Project Reactor y Spring Boot 2.0
  • Enrutamiento dinámico
  • Predicados y filtros actúan en rutas específicas
  • Disyuntor integrado Hystrix
  • 集成 Spring Cloud DiscoveryClient
  • Predicados y filtros fáciles de escribir
  • Limitante
  • Reescritura de ruta

contra Netflix Zuul

Zuul está basado en Servlet 2.5 (usando 3.x) y usa API de bloqueo. No admite conexiones largas, como WebSockets. Spring Cloud Gateway se basa en Spring Framework 5, Project Reactor y Spring Boot 2, utiliza una API sin bloqueo, es compatible con WebSockets y, debido a que está estrechamente integrado con Spring, será una mejor experiencia de desarrollo.

el termino

  • Ruta : este es el componente básico de una puerta de enlace. Está definido por un ID, un URI de destino, un conjunto de afirmaciones y un conjunto de filtros. Si la afirmación es verdadera, la ruta coincide.
  • Predicado (aserción) : este es un predicado de Java 8 . El tipo de entrada es uno ServerWebExchange. Podemos usarlo para hacer coincidir cualquier contenido de la solicitud HTTP, como encabezados o parámetros.
  • Filtro : Este es org.springframework.cloud.gateway.filter.GatewayFilterun ejemplo, podemos usarlo para modificar la solicitud y la respuesta.

Proceso

Inserte la descripción de la imagen aquí

El cliente envía una solicitud a Spring Cloud Gateway. Luego, busque la ruta que coincida con la solicitud en la asignación del controlador de puerta de enlace y envíela al controlador web de puerta de enlace. Luego, el controlador envía la solicitud a nuestro servicio real para ejecutar la lógica comercial a través de la cadena de filtro especificada y luego regresa.
El filtro está separado por una línea de puntos porque el filtro puede ejecutar la lógica empresarial antes ("pre") o después ("post") de que se envíe la solicitud de proxy.

Combate real

Usamos Zuul para implementar una puerta de enlace antes, y aquí usamos Spring Cloud Gateway para reemplazarla y lograr la misma función. Aquí continuamos utilizando los servicios que se han escrito antes y los iniciamos en secuencia:

  • eureka
  • productor
  • consumidor

Cree un nuevo proyecto Spring Boot estándar, asígnele el nombre de puerta de enlace y luego introduzca las siguientes coordenadas dependientes en pom.xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

El contenido del archivo de configuración application.yml es el siguiente

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
#      routes:
#        - id: default_path_to_http
#          uri: https://myurl
#          order: 10000
#          predicates:
#            - Path=/**
#          filters:
#            - SetPath=/
server:
  port: 10000
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka/
logging:
  level:
    org.springframework.cloud.gateway: debug

Instrucciones de configuración:

  • spring.cloud.gateway.discovery.locator.enabled: Si se combina con el registro de servicio en el componente de descubrimiento y se reenvía a la instancia de servicio específica a través de serviceId. La falseconfiguración predeterminada es truehabilitar la función de crear automáticamente rutas basadas en serviceId a través del centro de servicio.
  • spring.cloud.gateway.routesEs una matriz que se utiliza para cooperar con reglas de enrutamiento específicas. Aquí creé una default_path_to_httpruta con id , cuya configuración es reenviar solicitudes no coincidentes a https: // myurl. De hecho, después de que se activa el descubrimiento de servicios, si solo usa las reglas de enrutamiento creadas por defecto, esta ruta no está configurada, así que la comenté primero.
  • El servicio de puerta de enlace escucha en el puerto 10000
  • Especifique la dirección del registro para utilizar la función de descubrimiento de servicios
  • Ajuste el nivel de registro de los paquetes relacionados para facilitar la resolución de problemas

No es necesario modificar la clase de inicio de Spring Boot, se puede iniciar directamente y podemos ver nuestro servicio de puerta de enlace en Eureka después del inicio

Inserte la descripción de la imagen aquí

Luego visitamos http: // localhost: 10000 / consumer / hello / yujian como antes de usar Zuul

Esperábamos devolver "¡Hola yujian!" Como acceso directo al consumidor, pero de hecho salió mal y devolvió un error 404. Echemos un vistazo al registro

2020-08-23 15:05:09.562 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-PRODUCER applying {pattern=/EUREKA-PRODUCER/**} to Path
2020-08-23 15:05:09.564 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-PRODUCER applying filter {regexp=/EUREKA-PRODUCER/(?<remaining>.*), replacement=/${remaining}} to RewritePath
2020-08-23 15:05:09.566 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition matched: ReactiveCompositeDiscoveryClient_EUREKA-PRODUCER
2020-08-23 15:05:09.567 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER applying {pattern=/EUREKA-CONSUMER/**} to Path
2020-08-23 15:05:09.569 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER applying filter {regexp=/EUREKA-CONSUMER/(?<remaining>.*), replacement=/${remaining}} to RewritePath
2020-08-23 15:05:09.571 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition matched: ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER
2020-08-23 15:05:09.572 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_CLOUD-GATEWAY applying {pattern=/CLOUD-GATEWAY/**} to Path
2020-08-23 15:05:09.574 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_CLOUD-GATEWAY applying filter {regexp=/CLOUD-GATEWAY/(?<remaining>.*), replacement=/${remaining}} to RewritePath
2020-08-23 15:05:09.576 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition matched: ReactiveCompositeDiscoveryClient_CLOUD-GATEWAY

Puede ver que Spring Cloud Gateway crea automáticamente las rutas correspondientes para nuestro productor y consumidor, pero el patrón / expresión regular aquí están todos en mayúsculas. Probémoslo con mayúsculas.

Visitando http: // localhost: 20000 / EUREKA-CONSUMER / hello /? Name = yujian devolvió "¡Hola, yujian!", Luego mire el registro nuevamente

2020-08-23 15:06:07.664 DEBUG 16484 --- [ctor-http-nio-3] o.s.c.g.h.RoutePredicateHandlerMapping   : Route matched: ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER
2020-08-23 15:06:07.664 DEBUG 16484 --- [ctor-http-nio-3] o.s.c.g.h.RoutePredicateHandlerMapping   : Mapping [Exchange: GET http://localhost:20000/EUREKA-CONSUMER/hello/?name=yujian] to Route{id='ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER', uri=lb://EUREKA-CONSUMER, order=0, predicate=Paths: [/EUREKA-CONSUMER/**], match trailing slash: true, gatewayFilters=[[[RewritePath /EUREKA-CONSUMER/(?<remaining>.*) = '/${remaining}'], order = 1]], metadata={jmx.port=52177, management.port=9000}}
2020-08-23 15:06:07.664 DEBUG 16484 --- [ctor-http-nio-3] o.s.c.g.h.RoutePredicateHandlerMapping   : [a6395175-5] Mapped to org.springframework.cloud.gateway.handler.FilteringWebHandler@514419ac
2020-08-23 15:06:07.665 DEBUG 16484 --- [ctor-http-nio-3] o.s.c.g.handler.FilteringWebHandler      : Sorted gatewayFilterFactories: [[GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@4f263698}, order = -2147483648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@7810580e}, order = -2147482648], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@c42b297}, order = -1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@15a7e17}, order = 0], [[RewritePath /EUREKA-CONSUMER/(?<remaining>.*) = '/${remaining}'], order = 1], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@70115457}, order = 10000], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@a96a3c8}, order = 10100], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@7fb61a52}, order = 2147483646], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@5e56c74a}, order = 2147483647], [GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@1815b188}, order = 2147483647]]
2020-08-23 15:06:09.609 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-PRODUCER applying {pattern=/EUREKA-PRODUCER/**} to Path
2020-08-23 15:06:09.612 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-PRODUCER applying filter {regexp=/EUREKA-PRODUCER/(?<remaining>.*), replacement=/${remaining}} to RewritePath
2020-08-23 15:06:09.613 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition matched: ReactiveCompositeDiscoveryClient_EUREKA-PRODUCER
2020-08-23 15:06:09.615 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER applying {pattern=/EUREKA-CONSUMER/**} to Path
2020-08-23 15:06:09.616 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER applying filter {regexp=/EUREKA-CONSUMER/(?<remaining>.*), replacement=/${remaining}} to RewritePath
2020-08-23 15:06:09.617 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition matched: ReactiveCompositeDiscoveryClient_EUREKA-CONSUMER
2020-08-23 15:06:09.617 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_CLOUD-GATEWAY applying {pattern=/CLOUD-GATEWAY/**} to Path
2020-08-23 15:06:09.618 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition ReactiveCompositeDiscoveryClient_CLOUD-GATEWAY applying filter {regexp=/CLOUD-GATEWAY/(?<remaining>.*), replacement=/${remaining}} to RewritePath
2020-08-23 15:06:09.619 DEBUG 16484 --- [freshExecutor-0] o.s.c.g.r.RouteDefinitionRouteLocator    : RouteDefinition matched: ReactiveCompositeDiscoveryClient_CLOUD-GATEWAY

Se puede ver que Spring Cloud Gateway crea automáticamente una ruta para nuestro consumidor, similar a la siguiente

routes:
  - id: CompositeDiscoveryClient_CONSUMER
    uri: lb://CONSUMER
    order: 0
    predicates:
      - Path=/CONSUMER/**
    filters:
      - RewritePath=/CONSUMER/(?<segment>.*), /$\{
    
    segment}

Pero esta forma de capitalizar el serviceId es bastante dolorosa, aunque el registro Eureka muestra todas las mayúsculas por defecto, ¿es realmente bueno poner la ruta en mayúsculas en la URL? El único beneficio en el que puedo pensar es que el serviceId y la ruta se pueden distinguir claramente.

Si la URL en mayúsculas se convierte automáticamente en minúsculas en el navegador, puede intentar: borrar la caché, usar el modo incógnito (comando + shift + n) y usarlo directamente en la terminal curl.

La anterior es la regla de enrutamiento predeterminada basada en el descubrimiento de servicios. ¿Qué sucede si queremos personalizar la regla de enrutamiento?

Por ejemplo, nuestro servicio con estos servicios relacionados con el cliente (ah, ahora es una función única, solo con los clientes saludan, pero esto no tiene ningún efecto), esperamos que este camino de servicio para /customer/comenzar, específico para este caso, es decir /costomer/hello/{name}. Y necesitamos agregar un encabezado de respuesta a cada respuesta X-Response-Default-Foo: Default-Bar.

Modifiquemos la configuración, lo principal es agregar una ruta, el resto de configuraciones se mantienen sin cambios

routes:
  - id: service_customer
    uri: lb://CONSUMER
    order: 0
    predicates:
      - Path=/customer/**
    filters:
      - StripPrefix=1
      - AddResponseHeader=X-Response-Default-Foo, Default-Bar

El nuevo StripPrefixpuede aceptar un entero no negativo, y la implementación específica correspondiente es StripPrefixGatewayFilterFactoryque se puede ver en el nombre que su función es eliminar el prefijo, y ese entero corresponde al número de capas. Específicamente en este ejemplo, accedemos a través de Spring Cloud Gateway /customer/hello/yibo, luego, cuando el servicio de puerta de enlace reenvía la solicitud hacia atrás, se eliminará /customery el microservicio la recibirá /hello/yujian.

Ahora visitamos http: // localhost: 20000 / customer / hello / cloud y podemos ver que los datos se pueden devolver normalmente y que se ha agregado el encabezado de respuesta. En este momento, http: // localhost: 20000 / EUREKA-CONSUMER / hello / cloud aún puede devolver datos normalmente, pero no hay un encabezado de respuesta personalizado.

Inserte la descripción de la imagen aquí

Spring Cloud Gateway también admite la definición de enrutamiento a través de la API de transmisión de Java. La siguiente es una ruta equivalente configurada a través del archivo de configuración anterior y se puede usar con el archivo de configuración.

@Bean
public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
    
    
    // @formatter:off
    return builder.routes()
            .route(r -> r.path("/fluent/customer/**")
                         .filters(f -> f.stripPrefix(2)
                                        .addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
                         .uri("lb://CONSUMER")
                         .order(0)
                         .id("fluent_customer_service")
            )
            .build();
    // @formatter:on
}

para resumir

En este artículo, aprendimos brevemente sobre Spring Cloud Gateway y lo usamos para implementar un servicio de puerta de enlace simple. No solo presenta el enrutamiento predeterminado para microservicios al combinarse con el registro Eureka, sino que también presenta cómo personalizar el enrutamiento a través de archivos de configuración y API.Creo que ya tiene una comprensión preliminar de Spring Cloud Gateway. Continuaremos descubriendo características más poderosas de Spring Cloud Gateway en artículos futuros.

Supongo que te gusta

Origin blog.csdn.net/qq_44534541/article/details/109261352
Recomendado
Clasificación