1. 为什么是Spring Cloud Gateway
一句话,Spring Cloud已经放弃Netflix Zuul了。现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是基于过滤器的,是阻塞IO,不支持长连接。Zuul 2.x版本跟1.x的架构大一样,性能也有所提升。既然Spring Cloud已经不再集成Zuul 2.x了,那么是时候了解一下Spring Cloud Gateway了
可以看到,最新的Spring Cloud中的Zuul还是1.3.1版本
而且,官网中也明确说了不再维护Zuul了
(PS:顺便补充几个名词: 服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon))
2. API网关
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。
网关应当具备以下功能:
性能:API高可用,负载均衡,容错机制。
安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。
日志:日志记录(spainid,traceid)一旦涉及分布式,全链路跟踪必不可少。
缓存:数据缓存。
监控:记录请求响应数据,api耗时分析,性能监控。
限流:流量控制,错峰流控,可以定义多种限流规则。
灰度:线上灰度部署,可以减小风险。
路由:动态路由规则。
目前,比较流行的网关有:Nginx 、 Kong 、Orange等等,还有微服务网关Zuul 、Spring Cloud Gateway等等
对于 API Gateway,常见的选型有基于 Openresty 的 Kong、基于 Go 的 Tyk 和基于 Java 的 Zuul。这三个选型本身没有什么明显的区别,主要还是看技术栈是否能满足快速应用和二次开发。
以上说的这些功能,这些开源的网关组件都有,或者借助Lua也能实现,比如:Nginx + Lua
那要Spring Cloud Gateway还有什么用呢?
其实,我个人理解是这样的:
像Nginx这类网关,性能肯定是没得说,它适合做那种门户网关,是作为整个全局的网关,是对外的,处于最外层的;而Gateway这种,更像是业务网关,主要用来对应不同的客户端提供服务的,用于聚合业务的。各个微服务独立部署,职责单一,对外提供服务的时候需要有一个东西把业务聚合起来。
像Nginx这类网关,都是用不同的语言编写的,不易于扩展;而Gateway就不同,它是用Java写的,易于扩展和维护
Gateway这类网关可以实现熔断、重试等功能,这是Nginx不具备的
所以,你看到的网关可能是这样的:
3. Spring Cloud Gateway
3.1. 特性
基于Spring Framework 5、Project Reactor和Spring Boot 2.0构建
能够在任意请求属性上匹配路由
predicates(谓词) 和 filters(过滤器)是特定于路由的
集成了Hystrix断路器
集成了Spring Cloud DiscoveryClient
易于编写谓词和过滤器
请求速率限制
路径重写
3.2. 术语
Route : 路由是网关的基本组件。它由ID、目标URI、谓词集合和过滤器集合定义。如果聚合谓词为true,则匹配路由
Predicate : This is a Java 8 Function Predicate
Filter : 是GatewayFilter的一个实例,在这里,可以在发送下游请求之前或之后修改请求和响应
3.3. 原理
(PS:看到这张图是不是很熟悉,没错,很像SpringMVC的请求处理过程)
客户端向Spring Cloud Gateway发出请求。如果Gateway Handler Mapping确定请求与路由匹配,则将其发送给Gateway Web Handler。这个Handler运行通过特定于请求的过滤器链发送请求。过滤器可以在发送代理请求之前或之后执行逻辑。执行所有的“pre”过滤逻辑,然后发出代理请求,最后执行“post”过滤逻辑。
3.4. Route Predicate Factories
Spring Cloud Gateway 包含许多内置的 Route Predicate Factories
所有这些predicates用于匹配HTTP请求的不同属性
多个 Route Predicate Factories 可以通过逻辑与(and)结合起来一起使用
3.4.1. After Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
这个路由匹配“美国丹佛时间2017-01-20 17:42”之后的任意请求
3.4.2. Header Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
这个路由匹配“请求头包含X-Request-Id并且其值匹配正则表达式\d+”的任意请求
3.4.3. Method Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET
这个路由匹配任意GET请求
3.4.4. Path Route Predicate Factory
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Path=/foo/{segment},/bar/{segment}
这个路由匹配这样路径的请求,比如:/foo/1 或 /foo/bar 或 /bar/baz
3.4.5. Query Route Predicate Factory
这个Predicate有两个参数:一个必须的参数名和一个可选的正则表