一. 什么是网关(Gateway)
网关就是一个网络连接到另一个网络的关口。
在同一个项目或某一层级中,存在相似或重复的东西,我们就可以将这些相似重复的内容统一提取出来,向前或向后抽象成单独的一层。这个抽象的过程就是网关。
和AOP切面类似,但有区别。AOP切面是独立于单个项目的,也就是每个项目都需要自己实现AOP逻辑,并引入相应的AOP切面包。而网关是一种更加通用的方案,可以统一处理所有情况。
根据上图所示,最传统的统计接口调用次数的方案是每个接口被调用时都自己去统计一次,计数器加1。
在引入AOP切面后,将统计次数作为一个切面,每个接口被调用后,接口再去调用统计次数的方法。
网关则是作为最前面的一层,用户直接去调用网关,由网关根据用户请求的地址,找到对应的接口,然后调用它,同时调用后次数加1。
对于用户来说,无需关心接口到底是哪个项目的或者是谁开发的,只要知道自己需要什么功能,然后调用对应的网关即可。对开发者来说,也无需统计调用的次数,只要把自己的接口接入到网关中,让网关能找到并调用即可,网关会自己统计调用次数。
综上,网关可以理解成火车站的检票口,通过网关检票后,再去找到对应的车厢。
二. 网关的作用
统一进行一些操作或处理一些问题。
1.路由
起到转发的作用,比如有接口A和B,网关会去记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口。可以理解为转发的条件。
/a => 接口A /b => 接口B
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
这里就是说如果时间在2017年1月20后之后,都会去访问https://example.org 这个网址。
同理,还有Before、Between等。
参考文档:Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-after-route-predicate-factory
2.负载均衡
在路由的基础上,根据条件随机转发到其中某个机器上。
/c => 服务A/集群A。
3.统一处理跨域
网关统一处理跨越,不用在每个项目里单独处理。
参考文档:Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-cors-configuration
4.发布控制
灰度发布,比如上线了新接口,先给新接口分配20%的流量,旧接口80%,之后再逐渐调整比重。
参考文档:Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-weight-route-predicate-factory
5.流量染色
给请求(流量)添加一些标识,一般是设置请求头,或者添加新的请求头。
什么是流量染色?假设现在有个用户想要访问某个接口,但我希望用户不能绕过网关去访问,那么应该如何防止绕过网关呢?
可以给通过网关访问的用户请求增加一个标识,比如添加一个请求头source=gateway,所有经过网关的请求都会有这个请求头,接口就可以根据这个请求头去判断,如果没有的话,直接拒绝掉,说明不是通过网关的请求。这就是流量染色的一种应用。
另一个常见的应用是用于排查用户调用接口时出现的问题。为每个用户的每次调用都打上一个唯一的traceid,当出现问题时,通过这个id,下游服务可以快速追踪到具体的请求,从而逐层排查问题。
参考文档:Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-addrequestheader-gatewayfilter-factory
6.统一接口保护
- 限制请求
- 信息脱敏
- 降级(熔断)
- 限流
- 超时时间
- 重试(业务保护)
7.统一业务处理
把每个项目中都要做的通用逻辑放到上一层(网关),进行统一处理,比如接口调用次数统计。
8.统一鉴权
判断用户是否有权限进行操作,无论访问什么接口,都统一去判断权限,不用重复写。
9.访问控制
黑白名单,比如DDos IP。
10.统一日志
统一的请求、响应信息记录。
11.统一文档
将下游项目的文档进行聚合,在一个页面统一查看。类似于语雀的目录。
三. 网关分类
- 全局网关(接入层网关):实现负载均衡、请求日志等,不和业务逻辑绑定。
- 业务网关(微服务网关):有一些业务逻辑,作用是将请求转发到不同的业务/项目/接口/服务等。
全局网关通常层级较高,可能覆盖多个项目或微服务,主要用于请求的负载均衡,如Nginx、kong等。Nginx可以部署前端或后端,还能提供文件访问服务等多种功能,比较灵活,但操作不如Spring Cloud Gateway方便。
业务网关,特别是基于Spring Boot技术栈的项目,比较推荐使用Spring Cloud Gateway,性能较高,并允许使用Java编写逻辑,容易上手。Nginx或kong需要学习额外的语言和编程。
四.核心概念和逻辑
核心概念:
- 路由(Route):根据什么条件,转发请求到哪里。
- 断言(Predicate):一组规则、条件,用来确定如何转发路由。
- 过滤器(Filter):对请求进行一系列的处理,比如添加请求头、添加请求参数等。
实现逻辑:
- 客户端发起请求。
- Handler Mapping:根据断言,去将请求转发到对应的路由。
- Web Handler:处理请求(一层层经过过滤器)。
- 实际调用服务
Spring Cloud Gateway的两种配置方式:
- 配置式:更方便、规范,比较推荐。有简化版、全称版。就是在application.yml中写配置,也就是在创建项目时,将它作为一个依赖导入。
- 编程式:更灵活,但相对麻烦。
如上述这段官方提供的代码,就是创建了一个路由器,它的作用是当用户访问某个网址时,将其重定向到指定的网址。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie = mycookie, mycookievalue
上述是一个简化版的配置方式。
spring.cloud.gateway.routes:这是配置路由的属性。
- id:after_route:这是路由的唯一标识符,用于区分不同的路由。
uri:https://example.org:这是路由将请求转发到目标URI,即请求经过此路由后会被转发到https://example.org这个地址。
predicates:这个就是断言的配置属性,用于定义请求是否满足路由条件。
- Cookie = mycookie, mycookievalue:这是一个断言条件,指定了请求必须具有名为mycookie的Cookie,且其值必须为mycookievalue,才能匹配这个路由。
通过这个配置,当满足请求带有mycookie的Cookie且值为mycookievalue时,请求会被转发到https://example.org。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
上述是一个复杂版的配置方式,前面都没变,在predicates处设置的更加详细了。
- name: Cookie :断言条件,指定使用Cookie作为断言类型来检查请求。
args: 断言条件的参数配置。
name: mycookie:匹配名为mycookie的Cookie。
regexp: mycookievalue:使用正则表达式匹配mycookie的值是否为mycookievalue。
注意,predicates使用了复数形式,说明可以加多个规则(“-”代表列表)。
通过阅读官方文档后,断言(Predicates)的作用大概有:
- After 在xx时间之后
- Before 在xx时间之前
- Between 在xx时间之间
- 请求类别
- 请求头(包含Cookie)
- 查询参数
- 客户端地址
- 权重(可用来实现灰度测试)
过滤器(Filter)的作用大概有:
对请求头、响应头、请求参数的增删改查,可以这样理解。
- 添加请求头
- 添加请求参数
- 添加响应头
- 降级
- 限流
- 重试