学习一个东西首先要了解它主要是做什么的,有什么特性,自己写一写小demo,然后以demo中的各个点分别进行深入和发散,上来就看源码很不现实,本文主要介绍SCG的基本的特性、概念及SCG整体的架构。
SCG特性
以下翻译自https://github.com/spring-cloud/spring-cloud-gateway#features
- 基于Java8
- 基于Spring5
- 基于Spring2.0
- 支持动态路由,能够匹配任何请求属性上的路由(Route)
- 支持内置到Spring Handler映射中的路由匹配
- 支持基于HTTP请求的路由匹配(PATH、METHOD、HEADER、HOST)(Predicate)
- 过滤器作用于匹配的路由(Filter)
- 过滤器可以修改HTTP请求和HTTP响应(增加/修改Header、增加/修改请求参数、改写请求PATH等)
- 支持API或者配置驱动
- 支持Spring Cloud DiscoveryClient配置路由,与服务发现与注册配合使用
SCG是基于WebFlux的框架(不是中间件),使用Reactor模式,而WebFlux的底层是基于Netty的。
核心概念
以一个小demo为例(使用外部配置的方式),配置如下
spring:
cloud:
#SCG的配置,对应GatewayProperties
gateway:
routes:
- id: user-service #路由的编号(唯一)
uri: http://127.0.0.1:8080 #路由到的目标地址
predicates: # 断言,作为路由的匹配条件 对应RouteDefinition,可以配置多个
- Path=/login
filters:
- StripPrefix=1 #下边说
SCG的配置对应GatewayProperties
,里面又路由数组定义,还可以配置我们的默认过滤器。
- 由源码可知可以配置多个路由(有点儿像废话哈哈),在
RouteDefinition
中有配置断言(Predicate)和过滤器(Filter),都可以配置多个。
路由Route
路由Route是Gateway中最基本的组件之一,由id、uri、一组断言(Predicate)、一组过滤器(Filter)组成。一个请求如果满足某个路由的所有断言,则匹配该路由
- id:路由的唯一标识
- uri:路由指向的目标URI,请求最终被转发的地址
断言Predicate
Predicate:路由的匹配条件,如果配置多个需要同时满足才可匹配,Gateway已经内置了多种实现,如:Path、Method、Host等,上边我们使用的就是Path。
过滤器Filter
Filter:过滤器,对请求进行拦截,可实现自定义的功能。同样的,Gateway内置了多种Filter的实现,如熔断等,上边我们使用了StripPrefixGatewayFilterFactory
此过滤器会去掉请求的前缀,1
表示要从请求中去掉前缀数量,如请求地址为http://127.0.0.1:8080/test/login
,则真实转发到的地址会将/test去掉,修改为http://xxxx:8888/login
整体架构
我认为Route、Predicate、Filter即为SCG的核心,SCG都是围绕这三块进行展开的,对应源码中的就是如下三个部分。其中handler为Predicate断言。在spring-cloud-gateway-server工程中,v2.2.6.RELEASE版本由spring-cloud-gateway-core迁移过来。
下图为SCG的整个工作流程,有点类似SpringMVC。
- 首先是Handler部分,即为断言,通过断言最终匹配唯一路由Route
- 经过一系列的Filter链过滤
- 被Proxy Filter转发到目标URI,最终获得到service响应
- 响应同样的经过一系列的Filter链过滤
- 返回响应给客户端
配置驱动与API驱动
配置驱动上边已经演示过了,因此只演示API驱动
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes().route(
route -> route.path("/test/api/hello").and().host("*.spring.io")
.filters(
filter -> filter.addRequestHeader("hello", "502819LHJ").stripPrefix(1)
).uri("http://localhost:8088")
).build();
}
与配置驱动类似,也很灵活,可以*配置我们的断言和Filter。