本文会通过图文的方式由浅入深的描述 Spring Cloud Gateway (以下简称 gateway)的基本原理。
本文不涉及 gateway 的任何示例代码, 如有需要请参考官网 sample 。
阅读前, 需要读者提前掌握 gateway 的基本使用。至少要能读懂如下配置的含义:
spring:
cloud:
gateway:
routes:
- id: test_route
uri: lb://service-A
predicates:
- Path=/hello
filters:
- SetRequestHeader=X-Request-Red, Blue

以上便是 gateway 最基本的作用,它处理请求是逻辑是根据 配置的路由 对请求进行 预处理 和 转发
除此之外,还包括但不限于如下功能:
以上功能皆非本文讨论的重点内容,仅在此提及一下。
在讨论 gateway 工作原理之前, 我们先思考下, 如果让我们制作一个简单的网关应用, 实现方式有哪些。
根据上一章节末的描述可知, gateway 主要用于请求的转发处理。因此这里就涉及了网络通信的知识。



先简单翻译一下摘自 gateway 官网的描述:
SpringCloud Gateway 是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关。为了提升网关的性能,SpringCloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty。
然后我们结合 2.1 章节的分析, 可以将官网的描述成如下大白话:
Netty 是一款 出色 的网络通信框架。Reactor 模式通信框架 Netty,所以可以直接拿来用。PS: 至于什么是响应式编程, 为什么 gateway 基于这些技术能够实现高性能, 这些不是本文探讨的内容,感兴趣的读者可以自行去了解。
那么, 如何理解 Spring WebFlux,我们暂且就把它当做 Spring WebMVC。一个 web 框架。
他们之间很重要的一个区别就在于 webmvc 我们一般会基于 tomcat 容器去完成底层的网络通信, 而 webflux 是基于 Netty。
我们先来看下官网的描述:

从图中可以看出, 在 gateway 视角里,它在处理请求时, 划分成如下三大角色:
此时, 如果熟悉 Spring MVC 工作原理的可以看出,它和 Springmvc 的核心工作流程是类似的。
上面说到, gateway 底层还是基于 webflux。我们首先简单了解下 webflux 的工作原理, 然后延伸到 gateway 是如何基于 webflux 做扩展的。

以上是 webflux 处理请求的代码链路。我们着重看下标有颜色的类。
ReactorHttpHandlerAdapter,他的作用是将 netty 的请求、响应转为 http 的请求、响应, 并交给后面的类处理。FilteringWebHandler 是 gateway 对 webflux 的扩展。简单总结:
如果没看懂, 可以看完下面的内容, 再回过头来看本章节。
Gateway 有三个比较核心的组件, 可以结合如下路由配置看一看:
spring:
cloud:
gateway:
routes:
- id: test_route
uri: lb://service-A
predicates:
- Path=/hello
filters:
- SetRequestHeader=X-Request-Red, Blue
Route
gateway 中可以配置多个 Route。一个 Route 由路由 id,转发的 uri,多个 Predicates 以及多个 Filters 构成。处理请求时会按优先级排序,找到第一个满足所有 Predicates 的 Route。
Predicates
表示路由的匹配条件,可以用来匹配请求的各种属性,如请求路径、方法、header 等。一个 Route 可以包含多个 Predicates,多个 Predicates 最终会合并成一个。
Filter
过滤器包括了处理请求和响应的逻辑,可以分为 pre 和 post 两个阶段。多个 Filter 在 pre 阶段会按优先级高到低顺序执行,post 阶段则是反向执行。gateway 中的 Filter 分为如下两种:
Filter 在 gateway 中只会有一个实例,会对所有的 Route 都生效。Filter 是针对 Route 进行配置的,不同的 Route 可以使用不同的参数,因此会创建不同的实例。围绕上述三个组件, gateway 又衍生出了一些其他组件。
具体作用我们会在下面一一说明。

接下来,我们通过对上图进行讲解, 来详细介绍各个组件在 gateway 中的作用。
首先, gateway 本质就是一个 Springboot 应用, 他是通过 webflux 框架处理请求和响应,而 webflux 底层是基于 Netty。
GatewayAutoConfiguration 中配置的一些必要的组件 Bean。 比如:
GatewayProperties, 他里面保存了 gateway 的全部配置(其中就有路由配置信息)。GlobalFilter , gateway 默认的一些全局过滤器。RouteDefinitionLocator, 通过加载路由配置(比如读取 yaml 文件), 拿到 RouteDefinition , 里面是对路由的定义。RouteLocator, 负责组装 Route 对象, Route 对象中保存的是路由相关的信息。后续进行路由操作都是基于此对象。(请注意和 RouteDefinition 区分开)RoutePredicateHandlerMapping 和 org.springframework.cloud.gateway.handler.FilteringWebHandler , 这两个类是对 webflux 中两个组件的扩展实现,后续会说到具体作用。webflux 经过一层层处理后,然后会去调用 HandlerMapping 接口,拿到对应的 Handler。最后调用 Handler 的 handle 方法进行业务处理。HandlerMapping 和 Handler 两个接口,从而把处理请求的 活儿 从 webflux 手中接过来。Handler#handle 方法中,客户端发来的请求会经过上一步中过滤器链, 最终经过层层处理的请求会转发到对应服务中。RouteDefinition 定义了一个路由应该包含哪些匹配条件和过滤器,以及这些匹配条件和过滤器使用的参数, 它表示的是一个名词定义。在使用时 Gateway进行路由时, 会根据 RouteDefinition 对象提供的定义构造出 Route 对象,而 Route 里面提供了很多动作。
并且我们在前面提到: “一个 Route 可以包含多个 Predicates,多个 Predicates 最终会合并成一个。因此我们可以看到,关于 Predicates,RouteDefinition 里面定义的是一个集合, 而 Route 中只是一个对象。
public class RouteDefinition {
// ...
private List<PredicateDefinition> predicates = new ArrayList<>();
}
public class Route implements Ordered {
// ....
private final AsyncPredicate<ServerWebExchange> predicate;
}
RouteLocator 接口中定义了获取路由配置的方法,RouteLocator 有不同的实现,对应了不同的定义路由的方式。
public interface RouteLocator {
Flux<Route> getRoutes();
}
前文中我们提到,定义路由的其中一个方式是通过 RouteLocatorBuilder 提供的 API 来构建具体的 Route。
如下代码中定义了一个路由,其中包含了一个 path 匹配条件,以及一个添加响应 header 的 filter,请求转发的目标地址是 https://blog.csdn.net
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("route-id", r -> r.path("/test")
.filters(f -> f.addResponseHeader("X-TestHeader", "foobar"))
.uri("https://blog.csdn.net")
)
.build();
}
而 RouteDefinitionRouteLocator 是 RouteLocator 另一种常用的实现 。这种实现依赖于 RouteDefinitionLocator 来提供 RouteDefinition ,再由 RouteDefinition 构造路由。
CompositeRouteLocator 会把所有的 RouteLocator 的实现组合起来,再缓存到 CachingRouteLocator 中 。
因此当我们调用 getRoutes 方法获取路由集合时, 就会产生如下的调用关系:

RouteDefinitionLocator 接口定义了获取 RouteDefinition 的方法。
public interface RouteDefinitionLocator {
Flux<RouteDefinition> getRouteDefinitions();
}
前面我们多次提到 PropertiesRouteDefinitionLocator 可以通过解析 gateway 的配置文件中的路由配置拿到 RouteDefinition 对象集合
同上面的 RouteLocator 一样, 当 gateway 中有多个 RouteDefinitionLocator 实现时 , 同样会被 CompositeRouteDefinitionLocator 组合起来。
gateway 处理请求和响应的核心逻辑就在 Filter 中。gateway 本身实现提供了基础通用的过滤器,可以直接配置使用。 比如在请求前后, 分别添加请求头和响应头
我们再来看几个比较有意思的全局过滤器:
NettyRoutingFilter
在这个过滤器里面, 会发送转发请求到具体的 uri。
ReactiveLoadBalancerClientFilter
当 gateway 接入微服务时, 如果我们请求的服务存在多个实例,会在这里面进行负载均衡的处理。
本文通过图文结合的方式, 介绍了 Spring Cloud Gateway 的基本工作原理。
Spring Webflux 提供的扩展点,从而将请求与响应的工作转到自己手中。Spring Webflux 的底层是基于 Netty 和 Reactor, 可以有效的提升网关的性能。另外,本文的不足之处包括但不限于如下几点:
当然, 后面如果有条件会对以上几点进行补充说明。