Gateway:Spring Cloud API组件(非常详细)
这种客户端直接请求服务的方式存在以下问题:
当服务数量众多时,客户端需要维护大量的服务地址,这对于客户端来说,是非常繁琐复杂的。
在某些场景下可能会存在跨域请求的问题。
身份认证的难度大,每个微服务需要独立认证。
我们可以通过 API 来解决这些问题,下面就让我们来看看什么是 API 。
API
API 是一个搭建在客户端和微服务之间的服务,我们可以在 API 中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。API 就像整个微服务系统的门面一样,是系统对外的入口。有了它,客户端会先将请求发送到 API ,然后由 API 根据请求的标识信息将请求转发到微服务实例。

图1:两种服务访问方式对比
对于服务数量众多、复杂度较高、规模比较大的系统来说,使用 API 具有以下好处:
客户端通过 API 与微服务交互时,客户端只需要知道 API 地址即可,而不需要维护大量的服务地址,简化了客户端的开发。
客户端直接与 API 通信,能够减少客户端与各个服务的交互次数。
客户端与后端的服务耦度降低。
节省流量,提高性能,用户体验。
API 还提供了安全、流控、过滤、缓存、计费以及监控等 API 管理功能。
常见的 API 实现方案主要有以下 5 种:
Spring Cloud Gateway
Spring Cloud Netflix Zuul
Kong
Nginx+Lua
Traefik
本节,我们就对 Spring Cloud Gateway 进行详细介绍。
Spring Cloud Gateway
Spring Cloud Gateway 是 Spring Cloud 团队基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的高性能 API 组件。Spring Cloud Gateway 旨在提供一种简单而有效的途径来发送 API,并为它们提供横切关注点,例如:安全性,监控/指标和弹性。
Spring Cloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。
Spring Cloud Gateway 核心概念
Spring Cloud GateWay 最主要的功能就是路由转发,而在定义转发规则时主要涉及了以下三个核心概念,如下表。核心概念 | 描述 |
|---|---|
Route(路由) | 最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。 |
Predicate(断言) | 路由转发的判断条件,我们可以通过 Predicate 对 HTTP 请求进行匹配,例如请求方式、请求路径、请求头、参数等,如果请求与断言匹配成功,则将请求转发到相应的服务。 |
Filter(过滤器) | 过滤器,我们可以使用它对请求进行拦截和修改,还可以使用它对上文的响应进行再处理。 |
注意:其中 Route 和 Predicate 必须同时声明。
Spring Cloud Gateway 的特征
Spring Cloud Gateway 具有以下特性:基于 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 构建。
能够在任意请求属性上匹配路由。
predicates(断言) 和 filters(过滤器)是特定于路由的。
集成了 Hystrix 熔断器。
集成了 Spring Cloud DiscoveryClient(服务发现客户端)。
易于编写断言和过滤器。
能够限制请求频率。
能够重写请求路径。
Gateway 的工作流程
Spring Cloud Gateway 工作流程如下图。
图2:Spring Cloud Gateway 工作流程
Spring Cloud Gateway 工作流程说明如下:
客户端将请求发送到 Spring Cloud Gateway 上。
Spring Cloud Gateway 通过 Gateway Handler Mapping 找到与请求相匹配的路由,将其发送给 Gateway Web Handler。
Gateway Web Handler 通过指定的过滤器链(Filter Chain),将请求转发到实际的服务节点中,执行业务逻辑返回响应结果。
过滤器之间用虚线分开是因为过滤器可能会在转发请求之前(pre)或之后(post)执行业务逻辑。
过滤器(Filter)可以在请求被转发到服务端前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等。
过滤器可以在响应返回客户端之前,对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。
响应原路返回给客户端。
总而言之,客户端发送到 Spring Cloud Gateway 的请求需要通过一定的匹配条件,才能定位到真正的服务节点。在将请求转发到服务进行处理的过程前后(pre 和 post),我们还可以对请求和响应进行一些精细化控制。
Predicate 就是路由的匹配条件,而 Filter 就是对请求和响应进行精细化控制的工具。有了这两个元素,再加上目标 URI,就可以实现一个具体的路由了。
Predicate 断言
Spring Cloud Gateway 通过 Predicate 断言来实现 Route 路由的匹配规则。简单点说,Predicate 是路由转发的判断条件,请求只有满足了 Predicate 的条件,才会被转发到指定的服务上进行处理。使用 Predicate 断言需要注意以下 3 点:
Route 路由与 Predicate 断言的对应关系为“一对多”,一个路由可以包含多个不同断言。
一个请求想要转发到指定的路由上,就必须同时匹配路由上的所有断言。
- 当一个请求同时满足多个路由的断言条件时,请求只会被成功匹配的路由转发。

图3:Predicate 断言匹配
常见的 Predicate 断言如下表(假设转发的 URI 为 http://localhost:8001)。
断言 | 示例 | 说明 | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Path | - Path=/dept/list/** | 当请求路径与 /dept/list/** 匹配时,该请求才能被转发到 http://localhost:8001 上。 | |||||||||||||||||
Before | - Before=2021-10-20T11:47:34.255+08:00[Asia/Shanghai] | 在 2021 年 10 月 20 日 11 时 47 分 34.255 秒之前的请求,才会被转发到 http://localhost:8001 上。 | |||||||||||||||||
After | - After=2021-10-20T11:47:34.255+08:00[Asia/Shanghai] | 在 2021 年 10 月 20 日 11 时 47 分 34.255 秒之后的请求,才会被转发到 http://localhost:8001 上。 | |||||||||||||||||
Between | - Between=2021-10-20T15:18:33.226+08:00[Asia/Shanghai],2021-10-20T15:23:33.226+08:00[Asia/Shanghai] | 在 2021 年 10 月 20 日 15 时 18 分 33.226 秒 到 2021 年 10 月 20 日 15 时 23 分 33.226 秒之间的请求,才会被转发到 http://localhost:8001 服务器上。 | |||||||||||||||||
Cookie | - Cookie=name,c.biancheng网站站点" rel="nofollow" /> <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache网站站点" rel="nofollow" /> server: port: 9527 #端口号 spring: application: name: microServiceCloudGateway cloud: gateway: #路由配置 routes: #将 micro-service-cloud-provider-dept-8001 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 的地址 9527 - id: provider_dept_list_routh #路由 id,没有固定规则,但,建议与服务名对应 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: #以下是断言条件,必选全部符条件 - Path=/dept/list/** #断言,路径匹配 注意:Path 中 P 为大写 - Method=GET #只能时 GET 请求时,才能访问 eureka: instance: instance-id: micro-service-cloud-gateway-9527 hostname: micro-service-cloud-gateway client: fetch-registry: true register-with-eureka: true service-url: defaultZone: http://eureka700网站站点" rel="nofollow" /> - Path=/dept/list/** - Method=GET 只有当外部(客户端)发送到 micro-service-cloud-gateway-9527 的 HTTP 请求同时满足以上所有的断言时,该请求才会被转发到指定的服务端中(即 http://localhost:8001)。 3. 在 micro-service-cloud-gateway-9527 的主启动类上,使用 @EnableEurekaClient 注解开启 Eureka 客户端功能,代码如下。 package net.biancheng.c; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud网站站点" rel="nofollow" /> 图4:Spring Cloud Gateway 路由转发 Spring Cloud Gateway 动态路由 我们可以在配置文件中,将 Route 的 uri 地址修改为以下形式。 lb://service-name 以上配置说明如下: lb:uri 的协议,表示开启 Spring Cloud Gateway 的负载均衡功能。 service-name:服务名,Spring Cloud Gateway 会根据它获取到具体的微服务地址。 示例 下面我们就通过一个实例,来展示下 Spring Cloud Gateway 是如何实现动态路由的。1. 修改 micro-service-cloud-gateway-9527 中 application.yml 的配置,使用注册中心中的微服务名创建动态路由进行转发,配置如下。
GatewayFilter 过滤器 GatewayFilter 是 Spring Cloud Gateway 中提供的一种应用在单个或一组路由上的过滤器。它可以对单个路由或者一组路由上传入的请求和传出响应进行拦截,并实现一些与业务无关的功能,比如登陆状态校验、签名校验、权限校验、日志输出、流量监控等。GatewayFilter 在配置文件(例如 application.yml)中的写法与 Predicate 类似,格式如下。
Spring Cloud Gateway 内置了多达 31 种 GatewayFilter,下表中列举了几种常用的过滤器及其使用示例。
|




