Spring
在因Netflix
开源流产事件后,在不断的更换Netflix
相关的组件,好比:Eureka
、Zuul
、Feign
、Ribbon
等,Zuul
的替代产品就是SpringCloud Gateway
,这是Spring
团队研发的网关组件,能够实现限流、安全认证、支持长链接等新特性。html
Spring Cloud Gateway
是SpringCloud
的全新子项目,该项目基于Spring5.x
、SpringBoot2.x
技术版本进行编写,意在提供简单方便、可扩展的统一API路由管理方式。
概念解释:java
Route(路由)
:路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。Predicate(谓语、断言)
:路由转发的判断条件,目前SpringCloud Gateway
支持多种方式,常见如:Path
、Query
、Method
、Header
等。Filter(过滤器)
:过滤器是路由转发请求时所通过的过滤逻辑,可用于修改请求、响应内容。Spring Cloud GateWay 工做流程以下所示:git
客户端向Spring Cloud Gateway
发出请求。若是网关处理程序映射肯定请求与路由匹配,则将其发送到网关Web处理程序。此处理程序运行时经过特定于请求的筛选链发送请求。过滤器被虚线分隔的缘由是过滤器能够在发送代理请求以前或以后执行逻辑。执行全部“预”过滤逻辑,而后发出代理请求。在发出代理请求后,将执行“post”过滤器逻辑。spring
Spring Cloud Gateway
目前有两种方式进行配置:api
application.yml
配置文件方式RouteLocator
方法返回值在本章会侧重针对配置文件方式进行讲解,固然RouteLocator
方式也会简单的告诉你们的使用方式。安全
添加Spring Cloud Gateway
相关依赖,pom.xml
以下所示:cookie
//...省略部份内容 <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
内部提供的全部谓语、断言
,这样咱们才能目标性的进行学习,我整理出来了一个脑图,以下所示:app
每个Predicate
的使用,你能够理解为:当知足这种条件后才会被转发
,若是是多个,那就是都知足的状况下被转发。curl
经过Path
转发示例,咱们讲解下上面的两种配置,分别是application.yml
以及RouteLocator
。spring-boot
咱们在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
:路由的IDuri
:匹配路由的转发地址predicates
:配置该路由的断言,经过PredicateDefinition
类进行接收配置。在上面的配置中,当访问http://localhost:9090/api-boot-datasource-switch.html
时就会被自动转发到http://blog.yuqiyu.com/api-boot-datasource-switch.html
,这里要注意彻底匹配Path
的值时才会进行路由转发。
访问效果以下所示:
在上面的配置中,若是使用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 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 Gateway
的Before
断言采用的ZonedDateTime
进行匹配时间,这里要注意存在时区的问题,须要配置[Asia/Shanghai]
做为中国时区。
After Predicate
与Before
配置使用一致,匹配某一个时间点以后容许路由转发,以下所示配置:
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
。
那若是是一个时间段内容许请求转发,经过Before
、After
组合配置也能够完成,不过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
。
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。
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。
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:
咱们经过`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 // 不匹配
### 请求IP 方式匹配转发 `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`时,同时知足规则后请求才会被路由转发。 ## 源码位置 `Gitee`:<https://gitee.com/hengboy/spring-cloud-chapter/tree/master/SpringCloud/spring-cloud-gateway>