转载自  Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway

Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSockets,Spring Cloud Gateway 使用非阻塞 API,支持 WebSockets,支持限流等新特性

Spring Cloud Gateway

Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

相关概念:

  • Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。

  • Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。

  • Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。

工作流程:

客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

Spring Cloud Gateway 的特征:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0

  • 动态路由

  • Predicates 和 Filters 作用于特定路由

  • 集成 Hystrix 断路器

  • 集成 Spring Cloud DiscoveryClient

  • 易于编写的 Predicates 和 Filters

  • 限流

  • 路径重写

快速上手

Spring Cloud Gateway 网关路由有两种配置方式:

  • 在配置文件 yml 中配置

  • 通过@Bean自定义 RouteLocator,在启动主类 Application 中配置

这两种方式是等价的,建议使用 yml 方式进配置。

使用 Spring Cloud Finchley 版本,Finchley 版本依赖于 Spring Boot 2.0.6.RELEASE。

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.6.RELEASE</version><relativePath/> <!-- lookup parent from repository -->
</parent><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Finchley.SR2</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

经测试 Finchley.RELEASE 有 bug 多次请求会报空指针异常,SR2 是 Spring Cloud 的最新版本。

添加项目需要使用的依赖包

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

Spring Cloud Gateway 是使用 netty+webflux 实现因此不需要再引入 web 模块。

我们先来测试一个最简单的请求转发。

server:port: 8080
spring:cloud:gateway:routes:- id: neo_routeuri: http://www.ityouknow.compredicates:- Path=/spring-cloud

各字段含义如下:

  • id:我们自定义的路由 ID,保持唯一

  • uri:目标服务地址

  • predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。

  • filters:过滤规则,本示例暂时没用。

上面这段配置的意思是,配置了一个 id 为 neo_route 的路由规则,当访问地址 http://localhost:8080/spring-cloud时会自动转发到地址:http://www.ityouknow.com/spring-cloud。配置完成启动项目即可在浏览器访问进行测试,当我们访问地址http://localhost:8080/spring-cloud 时会展示页面展示如下:

明页面转发成功。

转发功能同样可以通过代码来实现,我们可以在启动类 GateWayApplication 中添加方法 customRouteLocator() 来定制转发规则。

@SpringBootApplication
public class GateWayApplication {public static void main(String[] args) {SpringApplication.run(GateWayApplication.class, args);}@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route("path_route", r -> r.path("/about").uri("http://ityouknow.com")).build();}}

上面配置了一个 id 为 path_route 的路由,当访问地址http://localhost:8080/about时会自动转发到地址:http://www.ityouknow.com/about和上面的转发效果一样,只是这里转发的是以项目地址/about格式的请求地址。

上面两个示例中 uri 都是指向了我的个人网站,在实际项目使用中可以将 uri 指向对外提供服务的项目地址,统一对外输出接口。

以上便是 Spring Cloud Gateway 最简单的两个请求示例,Spring Cloud Gateway 还有更多实用的功能接下来我们一一介绍。

路由规则

Spring Cloud Gateway 的功能很强大,我们仅仅通过 Predicates 的设计就可以看出来,前面我们只是使用了 predicates 进行了简单的条件匹配,其实 Spring Cloud Gataway 帮我们内置了很多 Predicates 功能。

Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping 做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。

Predicate 介绍

Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。and--与、or--或、negate--非

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。

通过时间匹配

Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。比如我们现在设置只有在2019年1月1日才会转发到我的网站,在这之前不进行转发,我就可以这样配置:

spring:cloud:gateway:routes:- id: time_routeuri: http://ityouknow.compredicates:- After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

Spring 是通过 ZonedDateTime 来对时间进行的对比,ZonedDateTime 是 Java 8 中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime 支持通过时区来设置时间,中国的时区是:Asia/Shanghai

After Route Predicate 是指在这个时间之后的请求都转发到目标地址。上面的示例是指,请求时间在 2018年1月20日6点6分6秒之后的所有请求都转发到地址http://ityouknow.com+08:00是指时间和UTC时间相差八个小时,时间地区为Asia/Shanghai

添加完路由规则之后,访问地址http://localhost:8080会自动转发到http://ityouknow.com

Before Route Predicate 刚好相反,在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的 After 改为 Before,如下:

spring:cloud:gateway:routes:- id: after_routeuri: http://ityouknow.compredicates:- Before=2018-01-20T06:06:06+08:00[Asia/Shanghai]

就表示在这个时间之前可以进行路由,在这时间之后停止路由,修改完之后重启项目再次访问地址http://localhost:8080,页面会报 404 没有找到地址。

除过在时间之前或者之后外,Gateway 还支持限制路由请求在某一个时间段范围内,可以使用 Between Route Predicate 来实现。

spring:cloud:gateway:routes:- id: after_routeuri: http://ityouknow.compredicates:- Between=2018-01-20T06:06:06+08:00[Asia/Shanghai], 2019-01-20T06:06:06+08:00[Asia/Shanghai]

这样设置就意味着在这个时间段内可以匹配到此路由,超过这个时间段范围则不会进行匹配。通过时间匹配路由的功能很酷,可以用在限时抢购的一些场景中。

通过 Cookie 匹配

Cookie Route Predicate 可以接收两个参数,一个是 Cookie name ,一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。

spring:cloud:gateway:routes:- id: cookie_routeuri: http://ityouknow.compredicates:- Cookie=ityouknow, kee.e

使用 curl 测试,命令行输入:

curl http://localhost:8080 --cookie "ityouknow=kee.e"

则会返回页面代码,如果去掉--cookie "ityouknow=kee.e",后台汇报 404 错误。

通过 Header 属性匹配

Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

spring:cloud:gateway:routes:- id: header_routeuri: http://ityouknow.compredicates:- Header=X-Request-Id, \d+

使用 curl 测试,命令行输入:

curl http://localhost:8080  -H "X-Request-Id:666666"

则返回页面代码证明匹配成功。将参数-H "X-Request-Id:666666"改为-H "X-Request-Id:neo"再次执行时返回404证明没有匹配。

通过 Host 匹配

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

spring:cloud:gateway:routes:- id: host_routeuri: http://ityouknow.compredicates:- Host=**.ityouknow.com

使用 curl 测试,命令行输入:

curl http://localhost:8080  -H "Host: www.ityouknow.com"
curl http://localhost:8080  -H "Host: md.ityouknow.com"

经测试以上两种 host 均可匹配到 host_route 路由,去掉 host 参数则会报 404 错误。

通过请求方式匹配

可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。

spring:cloud:gateway:routes:- id: method_routeuri: http://ityouknow.compredicates:- Method=GET

使用 curl 测试,命令行输入:

# curl 默认是以 GET 的方式去请求
curl http://localhost:8080

测试返回页面代码,证明匹配到路由,我们再以 POST 的方式请求测试。

# curl 默认是以 GET 的方式去请求
curl -X POST http://localhost:8080

返回 404 没有找到,证明没有匹配上路由

通过请求路径匹配

Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。

spring:cloud:gateway:routes:- id: host_routeuri: http://ityouknow.compredicates:- Path=/foo/{segment}

如果请求路径符合要求,则此路由将匹配,例如:/foo/1 或者 /foo/bar。

使用 curl 测试,命令行输入:

curl http://localhost:8080/foo/1
curl http://localhost:8080/foo/xx
curl http://localhost:8080/boo/xx

经过测试第一和第二条命令可以正常获取到页面返回值,最后一个命令报404,证明路由是通过指定路由来匹配。

通过请求参数匹配

Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。

spring:cloud:gateway:routes:- id: query_routeuri: http://ityouknow.compredicates:- Query=smile

这样配置,只要请求中包含 smile 属性的参数即可匹配路由。

使用 curl 测试,命令行输入:

curl localhost:8080?smile=x&id=2

经过测试发现只要请求汇总带有 smile 参数即会匹配路由,不带 smile 参数则不会匹配。

还可以将 Query 的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由。

spring:cloud:gateway:routes:- id: query_routeuri: http://ityouknow.compredicates:- Query=keep, pu.

这样只要当请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由。

使用 curl 测试,命令行输入:

curl localhost:8080?keep=pub

测试可以返回页面代码,将 keep 的属性值改为 pubx 再次访问就会报 404,证明路由需要匹配正则表达式才会进行路由。

通过请求 ip 地址进行匹配

Predicate 也支持通过设置某个 ip 区间号段的请求才会路由,RemoteAddr Route Predicate 接受 cidr 符号(IPv4 或 IPv6 )字符串的列表(最小大小为1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

spring:cloud:gateway:routes:- id: remoteaddr_routeuri: http://ityouknow.compredicates:- RemoteAddr=192.168.1.1/24

可以将此地址设置为本机的 ip 地址进行测试。

curl localhost:8080

果请求的远程地址是 192.168.1.10,则此路由将匹配。

组合使用

上面为了演示各个 Predicate 的使用,我们是单个单个进行配置测试,其实可以将各种 Predicate 组合起来一起使用。

例如:

spring:cloud:gateway:routes:- id: host_foo_path_headers_to_httpbinuri: http://ityouknow.compredicates:- Host=**.foo.org- Path=/headers- Method=GET- Header=X-Request-Id, \d+- Query=foo, ba.- Query=baz- Cookie=chocolate, ch.p- After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发

总结

通过今天的学习发现 Spring Cloud Gateway 使用非常的灵活,可以根据不同的情况来进行路由分发,在实际项目中可以自由组合使用。同时 Spring Cloud Gateway 还有更多很酷的功能,比如 Filter 、熔断和限流等,下次我们继续学习 Spring Cloud Gateway 的高级功能。

所有代码都在这里:https://github.com/ityouknow/spring-cloud-examples

Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway相关推荐

  1. Spring Cloud之(十八)微服务网关GateWay

    十八.微服务网关GateWay Zuul 1.x 是一个基于阻塞 IO 的 API Gateway 以及 Servlet:直到 2018 年 5 月,Zuul 2.x(基于Netty,也是非阻塞的,支 ...

  2. Spring Cloud浅谈个人尝鲜------Zuul 服务网关(五)

    Spring Cloud浅谈个人尝鲜------Zuul 服务网关(五) 前面几篇文章我们学习了Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止 ...

  3. Spring Cloud与微服务学习总结(2)——Spring Cloud相较于Dubbo等RPC服务框架的优势

    摘要: 目前,Spring Cloud在国内的知名度并不高,在前阵子的求职过程中,与一些互联网公司的架构师.技术VP或者CTO在交流时,有些甚至还不知道该项目的存在.可能这也与国内阿里巴巴开源服务治理 ...

  4. 阿里新框架发布!干掉Spring Cloud,换下Dubbo,微服务王者来了!

    目前,但凡谈及微服务技术选型,就必然会遇到一个两难的抉择,到底该采用Dubbo,还是该选择Spring Cloud呢? 当初阿里于2017年宣布重新开源Dubbo,近年来Dubbo发展速度和势头可谓是 ...

  5. Spring Cloud Alibaba基础教程:几种服务消费方式(RestTemplate、WebClient、Feign)

    热门:Spring Cloud Greenwich.RELEASE 正式发布!一个非常有看头的版本! 通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现&g ...

  6. 《Spring Cloud Netflix官方文档》2. 服务发现:Eureka服务器

    2. 服务发现:Eureka服务器 2.1 如何创建Eureka服务器 引用org.springframework.cloud的spring-cloud-starter-eureka-server就可 ...

  7. 《Spring Cloud Netflix官方文档》1.服务发现:Eureka客户端

    1.     服务发现:Eureka客户端 服务发现是微服务架构的关键原则之一.使用手动配置或一些约定方式来处理多服务多实例的方式是非常困难,并且十分脆弱的.Eureka同时是Netflix服务发现的 ...

  8. 微服务等于Spring Cloud?一文告诉你微服务到底是什么

    作者:TIM XU 原文:https://xiaoxubeii.github.io/articles/microservices-architecture-introduction/ 1 微服务初探 ...

  9. 【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战

    文章目录 前言 I.微服务与Spring Cloud II.Nacos 注册中心 III.Spring Cloud Alibaba Nacos 实战 1.新建父工程 2.新建demo-a 服务 3.新 ...

最新文章

  1. android toast几种使用方法 (转)
  2. webuploader 获取文件md5_WebUploader API文档
  3. php 7 class 初始化 销毁_在 PHP 中使用和管理 Session
  4. 以太网的phy寄存器分析
  5. jaxws-ri下载链接
  6. pyqt5设置dialog的标题_PyQt5教程——对话框(6)
  7. psasp和matlab,PSASP与Matlab/SimPowerSystems联合仿真接口方法研究
  8. FW: Why PUT and DELETE?铪铪
  9. RGB与十六进制颜色进行互转
  10. 20220601超简单百度地图街景图片爬取+绿视率计算
  11. 无线破解攻击工具Aircrack-ng使用详解
  12. 如何设置zotero连接到坚果云
  13. 真实案例,手把手教你构建用户画像
  14. 计算机运算器发展趋势,2020计算器市场发展现状及及前景分析
  15. 一个典型的微型计算机绘图系统,机械制图考试理论知识练习题
  16. 第十三周 任务四
  17. 生成SAML所需X509证书
  18. 行车百科系列之(四): 交警执法宝典(内部资料)
  19. 读懂algebraic distances on graphs
  20. 市场调研-全球与中国化妆品级乙基己基甘油市场现状及未来发展趋势

热门文章

  1. 367. 有效的完全平方数(二分法)
  2. [JavaWeb-JDBC]JDBC概念
  3. 编程 音量键_盘点市面上那些千元级高逼格的键盘 灯光炫酷 多宏编程
  4. python实现辗转相除法求最大公约数和最小公倍数
  5. word List28
  6. 大话数据结构学习笔记一:第一章
  7. 数列递推(牛客练习赛83)(数学、分块)
  8. 伯努利数(详解 + 例题 :P3711 仓鼠的数学题)
  9. P6329 【模板】点分树 | 震波
  10. AGC022E - Median Replace