Spring Cloud GateWay 路由转发规则介绍详解

Spring在因Netflix开源流产事件后,在不断的更换Netflix相关的组件,比如:EurekaZuulFeignRibbon等,Zuul的替代产品就是SpringCloud Gateway,这是Spring团队研发的网关组件,可以实现限流、安全认证、支持长连接等新特性。

Spring Cloud Gateway

Spring Cloud GatewaySpringCloud的全新子项目,该项目基于Spring5.xSpringBoot2.x技术版本进行编写,意在提供简单方便、可扩展的统一API路由管理方式。

概念解释:

  • Route(路由):路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。
  • Predicate(谓语、断言):路由转发的判断条件,目前SpringCloud Gateway支持多种方式,常见如:PathQueryMethodHeader等。
  • Filter(过滤器):过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容。

Spring Cloud GateWay 工作流程如下所示:

客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。此处理程序运行时通过特定于请求的筛选链发送请求。过滤器被虚线分隔的原因是过滤器可以在发送代理请求之前或之后执行逻辑。执行所有“预”过滤逻辑,然后发出代理请求。在发出代理请求后,将执行“post”过滤器逻辑。

开始使用

Spring Cloud Gateway目前有两种方式进行配置:

  • application.yml配置文件方式
  • 通过@Bean注解RouteLocator方法返回值

在本章会侧重针对配置文件方式进行讲解,当然RouteLocator方式也会简单的告诉大家的使用方式。

添加依赖

添加Spring Cloud Gateway相关依赖,pom.xml如下所示:

//...省略部分内容
<properties>
  <java.version>1.8</java.version>
  <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
 </properties>

 <dependencies>
  <!--Spring Cloud Gateway-->
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>
//...省略部分内容

Spring Cloud Gateway Predicates

在我们开始本章内容之前我们要来先了解下Spring Cloud Gateway内部提供的所有谓语、断言,这样我们才能目标性的进行学习,我整理出来了一个脑图,如下所示:

每一个Predicate的使用,你可以理解为:当满足这种条件后才会被转发,如果是多个,那就是都满足的情况下被转发。

Path 方式匹配转发

通过Path转发示例,我们讲解下上面的两种配置,分别是application.yml以及RouteLocator

配置文件匹配地址转发

我们在application.yml配置文件内添加对应的路由配置,如下所示:

spring:
 application:
 name: spring-cloud-gateway-sample
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   # 匹配路径转发
   - Path=/api-boot-datasource-switch.html
# 端口号
server:
 port: 9090

先来解释下route的组成部分:

  • id:路由的ID
  • uri:匹配路由的转发地址
  • predicates:配置该路由的断言,通过PredicateDefinition类进行接收配置。

在上面的配置中,当访问http://localhost:9090/api-boot-datasource-switch.html时就会被自动转发到http://blog.yuqiyu.com/api-boot-datasource-switch.html,这里要注意完全匹配Path的值时才会进行路由转发。

访问效果如下所示:

RouteLocator 匹配路径转发

在上面的配置中,如果使用RouteLocator方式该怎么进行配置呢?

如下所示:

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
 return builder.routes()
 .route("blog", r ->
   r.path("/api-boot-datasource-switch.html").uri("http://blog.yuqiyu.com"))
 .build();
}

Before 方式匹配转发

当部署有访问时间限制的接口时,我们可以通过Before Predicate来完成某一个时间点之前允许访问,过时后则不允许转发请求到具体的服务,配置如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Before=2019-05-01T00:00:00+08:00[Asia/Shanghai]

在上面配置中,我们允许2019-05-01日凌晨之前通过路由转发到http://blog.yuqiyu.com,通过查看org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory源码我们发现,Spring Cloud GatewayBefore断言采用的ZonedDateTime进行匹配时间,这里要注意存在时区的问题,需要配置[Asia/Shanghai]作为中国时区。

After 方式匹配转发

After PredicateBefore配置使用一致,匹配某一个时间点之后允许路由转发,如下所示配置:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - After=2019-04-29T00:00:00+08:00[Asia/Shanghai]

在上面配置中允许2019-04-29凌晨之后进行转发到http://blog.yuqiyu.com

Between 方式匹配转发

那如果是一个时间段内允许请求转发,通过BeforeAfter组合配置也可以完成,不过Spring Cloud Gateway还是提供了Between方式,如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Between=2019-04-29T00:00:00+08:00[Asia/Shanghai], 2019-05-01T00:00:00+08:00[Asia/Shanghai]

在上面配置中,允许在2019-04-29日凌晨后 & 2019-05-01凌晨之前请求转发到http://blog.yuqiyu.com

Cookie 方式匹配转发

Spring Cloud Gateway 还提供了根据Cookie值的方式匹配转发请求,如果请求中所携带的Cookie值与配置的Predicate匹配,那么就可以被允许转发到指定地址,如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Cookie=hengboy, yuqiyu

在上面配置中,如果客户端发送请求时携带了"hengboy=yuqiyu"的Cookie信息,则允许请求转发。

测试Cookie方式转发:

curl http://localhost:9090 --cookie "hengboy=yuqiyu"

通过上面方式我们是可以成功转发请求的,如果我们修改Cookie的值,就会导致无法转发,出现404。

Header 方式匹配转发

Spring Cloud Gateway可以根据发送请求的Header信息进行匹配转发,加入我们可以根据X-Request-Id的值进行匹配,如下所示:

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

在上面配置中,如果X-Request-Id的值为数字,那么就可以转发到http://blog.yuqiyu.com,我们通过如下方式进行测试:

curl http://localhost:9090 -H "X-Request-Id:123456"

如果头信息为X-Request-Id:abc时,就会转发失败,出现404。

Host 方式匹配转发

Spring Cloud Gateway可以根据Host主机名进行匹配转发,如果我们的接口只允许**.yuqiyu.com域名进行访问,那么配置如下所示:

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

测试如下所示:

1. curl http://localhost:9090 -H "Host: yuqiyu.com"  	// 匹配
2. curl http://localhost:9090 -H "Host: api.yuqiyu.com"		// 匹配
3. curl http://localhost:9090 -H "Host: admin.yuqiyu.com" // 匹配
3. curl http://localhost:9090 -H "Host: hengboy.com" 	 // 不匹配

请求方式 方式匹配转发

Rest请求风格的接口内往往会存在多种请求方式的接口,如果我们的接口只允许POST请求访问,那么配置如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Method=POST

发送GET请求测试:

~ curl http://localhost:9090
{"timestamp":"2019-04-29T06:27:41.121+0000","path":"/","status":404,"error":"Not Found","message":null}

我们的请求并未被Spring Cloud Gateway进行转发,那么我们再来通过POST请求进行测试:

curl -X POST http://localhost:9090

是可以被转发到目标地址uri的,不过我的这个博客是OSS部署的,阿里云限制了POST访问,尽管如此我们也证明了可以转发。

请求参数 方式匹配转发

Spring Cloud GateWay还支持根据指定的参数进行匹配,Query方式的Predicate也有两种方式匹配情况,如下所示:

请求中存在xxx参数

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Query=xxx

我们通过curl http://localhost:9090\?xxx\=123是可以被成功转发的,只要参数存在xxx就会被成功转发,否则出现404转发失败。

请求中存在xxx参数且值为zzz

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Query=xxx, zzz

根据上面配置,我们限定了参数xxx必须为zzz时才会被成功转发,否则同样会出现404抓发失败。

请求路径 方式匹配转发

Spring Cloud Gateway提供了请求路径变量方式匹配转发,如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Path=/article/{articleId}

在上面配置中{articleId}是一个路径变量,可以是任意值,匹配/article/1/article/abc等,测试如下所示:

~ curl http://localhost:9090/article/1			// 匹配
~ curl http://localhost:9090/article/abc		// 匹配
~ curl http://localhost:9090/article/1/1		// 不匹配

Spring Cloud Gateway可以限制允许访问接口的客户端IP地址,配置后只对指定IP地址的客户端进行请求转发,配置如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - RemoteAddr=192.168.1.56/24

在上面我们配置了192.168.1.56/24,其中192.168.1.56是客户端的IP地址,而24则是子网掩码。

组合示例

相同的Predicate也可以配置多个,请求的转发是必须满足所有的Predicate后才可以进行路由转发,组合使用示例如下所示:

spring:
 cloud:
 gateway:
  routes:
  - id: blog
   uri: http://blog.yuqiyu.com
   predicates:
   - Query=author, hengboy
   - Query=yuqiyu
   - Method=GET
   - Cookie=hengboy, yuqiyu
   - Header=X-Request-Id, \d+
   - RemoteAddr=192.168.1.56/24

总结

本章节讲解了Spring Cloud Gateway的相关谓词、断言基本使用方式,GateWay内部提供了很多种灵活的路由转发规则,在同一个路由内存在多个Predicate时,同时满足规则后请求才会被路由转发。

源码位置

Giteehttps://gitee.com/hengboy/spring-cloud-chapter/tree/master/SpringCloud/spring-cloud-gateway

ApiBoothttps://gitee.com/hengboy/api-boothttps://github.com/hengboy/api-boot

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2019-05-04

详解Spring Cloud Gateway 数据库存储路由信息的扩展方案

动态路由背景 ​ 无论你在使用Zuul还是Spring Cloud Gateway 的时候,官方文档提供的方案总是基于配置文件配置的方式 例如: # zuul 的配置形式 routes: pig-auth: path: /auth/** serviceId: pig-auth stripPrefix: true # gateway 的配置形式 routes: - id: pigx-auth uri: lb://pigx-auth predicates: - Path=/auth/** filte

详解Spring Cloud Gateway基于服务发现的默认路由规则

1.Spring Gateway概述 1.1 什么是Spring Cloud Gateway Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式.Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由

详解Spring Cloud Gateway 限流操作

开发高并发系统时有三把利器用来保护系统:缓存.降级和限流. API网关作为所有请求的入口,请求量大,我们可以通过对并发访问的请求进行限速来保护系统的可用性. 常用的限流算法比如有令牌桶算法,漏桶算法,计数器算法等. 在Zuul中我们可以自己去实现限流的功能 (Zuul中如何限流在我的书 <Spring Cloud微服务-全栈技术与案例解析>  中有详细讲解) ,Spring Cloud Gateway的出现本身就是用来替代Zuul的. 要想替代那肯定得有强大的功能,除了性能上的优势之外,Spr

详解spring cloud构建微服务架构的网关(API GateWay)

前言 在我们前面的博客中讲到,当服务A需要调用服务B的时候,只需要从Eureka中获取B服务的注册实例,然后使用Feign来调用B的服务,使用Ribbon来实现负载均衡,但是,当我们同时向客户端暴漏多个服务的时候,客户端怎么调用我们暴漏的服务了,如果我们还想加入安全认证,权限控制,过滤器以及动态路由等特性了,那么就需要使用Zuul来实现API GateWay了,下面,我们先来看下Zuul怎么使用. 一.加入Zuul的依赖 <dependency> <groupId>org.spri

详解spring cloud使用Hystrix实现单个方法的fallback

本文介绍了spring cloud-使用Hystrix实现单个方法的fallback,分享给大家,具体如下: 一.加入Hystrix依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> 二.编写Controller package c

详解Spring Cloud 跨服务数据聚合框架

AG-Merge Spring Cloud 跨服务数据聚合框架 解决问题 解决Spring Cloud服务拆分后分页数据的属性或单个对象的属性拆分之痛, 支持对静态数据属性(数据字典).动态主键数据进行自动注入和转化, 其中聚合的静态数据会进行 一级混存 (guava). 举个栗子: 两个服务,A服务的某张表用到了B服务的某张表的值,我们在对A服务那张表查询的时候,把B服务某张表的值聚合在A服务的那次查询过程中 示例 具体示例代码可以看 ace-merge-demo 模块 |------- ac

详解spring cloud整合Swagger2构建RESTful服务的APIs

前言 在前面的博客中,我们将服务注册到了Eureka上,可以从Eureka的UI界面中,看到有哪些服务已经注册到了Eureka Server上,但是,如果我们想查看当前服务提供了哪些RESTful接口方法的话,就无从获取了,传统的方法是梳理一篇服务的接口文档来供开发人员之间来进行交流,这种情况下,很多时候,会造成文档和代码的不一致性,比如说代码改了,但是接口文档没有改等问题,而Swagger2则给我们提供了一套完美的解决方案,下面,我们来看看Swagger2是如何来解决问题的. 一.引入Swag

详解Spring cloud使用Ribbon进行Restful请求

写在前面 本文由markdown格式写成,为本人第一次这么写,排版可能会有点乱,还望各位海涵.  主要写的是使用Ribbon进行Restful请求,测试各个方法的使用,代码冗余较高,比较适合初学者,介意轻喷谢谢. 前提 一个可用的Eureka注册中心(文中以之前博客中双节点注册中心,不重要) 一个连接到这个注册中心的服务提供者 一个ribbon的消费者 注意:文中使用@GetMapping.@PostMapping.@PutMapping.@DeleteMapping等注解需要升级 spring

详解spring cloud config实现datasource的热部署

关于spring cloud config的基本使用,前面的博客中已经说过了,如果不了解的话,请先看以前的博客 spring cloud config整合gitlab搭建分布式的配置中心 spring cloud config分布式配置中心的高可用 今天,我们的重点是如何实现数据源的热部署. 1.在客户端配置数据源 @RefreshScope @Configuration// 配置数据源 public class DataSourceConfigure { @Bean @RefreshScope

详解spring cloud config整合gitlab搭建分布式的配置中心

在前面的博客中,我们都是将配置文件放在各自的服务中,但是这样做有一个缺点,一旦配置修改了,那么我们就必须停机,然后修改配置文件后再进行上线,服务少的话,这样做还无可厚非,但是如果是成百上千的服务了,这个时候,就需要用到分布式的配置管理了.而spring cloud config正是用来解决这个问题而生的.下面就结合gitlab来实现分布式配置中心的搭建.spring cloud config配置中心由server端和client端组成, 前提:在gitlab中的工程下新建一个配置文件config