API网关:SpringCloud Gateway

Posted 无情的代码Bug

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了API网关:SpringCloud Gateway相关的知识,希望对你有一定的参考价值。

将所有的微服务直接对外暴露,出现安全方面的各种问题。


客户端可以直接向每个微服务暴露的细粒度API不匹配。


又或者服务使用的协议不是Web友好协议。有些服务使用Thirft二进制RPC,也可以使用AMQP消息传递协议。


微服务难重构,合并两个服务,又或者一个服务拆分成两个或者更多的服务。


解决的方案就是使用API网关。是后端服务的唯一入口。


除此之外,还可以负责验证,监控,负载均衡,限流,降级。


SpringCloud Gateway


SpringCloud Gateway提供一种简单而且简单的有效途径来转发请求。


zuul和nginx很像,每次I/O操作都是从工作线程中选择一个执行,请求线程被阻塞直到工作线程完成,zuul用java实现,jvm会有一次加载较慢的情况,zuul的性能较差。


而Springcloud Gateway使用的非阻塞API。在提供的功能上和实际性能方面,表现很优异。


网关服务(源码分析)



1,请求发送到网关,DispatcherHandler是HTTP的中央分发器。将请求匹配到响应的HandlerMapping。

2,请求和处理器会有一个映射关系

3,到达网关的Web处理器,该WebHandler代理了一系列网关过滤器和全局过滤器的实例,比如说对请求或者响应的头部进行处理。

4,转发到具体代理服务



初始化配置


网关属性的配置定义,GatewayProperties是网关中主要的配置属性类。

API网关:SpringCloud Gateway


三个属性:路由,默认过滤器,MediaType的配置。


routes是一个列表,对象的属性就是RouteDefinitioon

defaultFilters是默认的路由过滤器

streamingMediaTypes支持两种类型:APPLICATION_STREAM_JSON和TEXT_EVENT_STREAM。


网关处理器

API网关:SpringCloud Gateway



到达网关后,会有各种Web处理器对请求进行匹配和处理。


下面具体看一下网关收到请求后,如何匹配HandlerMapping。


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway


DispatcherHandler的构造函数初始化HandlerMapping,HanderMapping是一个定义了请求与处理器对象映射的接口有多个实现类。


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

AbstractHandlerMapping的getHandler返回响应的Web处理器。随后到达DispatchHandler的invokeHandler中,调用响应的WebHandler,获得该对应的适配器

API网关:SpringCloud Gateway


API网关:SpringCloud Gateway


路由断言的HandlerMapping


API网关:SpringCloud Gateway

RoutePredicateHandlerMapping的构造函数有两个参数:FilteringWebHandler网关过滤器,RouteLocator路由定位器,setOrder(1)设置该对象初始化的优先级。


API网关:SpringCloud Gateway

1,设置GATEWAY_HANDLER_MAPPER_ATTR: RoutePredicateHandlerInternal

2,设置GATEWAY_ROUTE_ATTR:匹配的Route


API网关:SpringCloud Gateway

1,顺序匹配请求对应的Route

2,检验Route的有效性


RouteLocator接口用于获取在网关中定义的路由,根据请求的信息,与路由定义的断言进行匹配(按照路由定义的优先级),最后设置GATEWAY_ROUTE_ATTR为匹配的Route,返回对应的Handler。



过滤器的Web处理器


FilteringWebHandler通过创建所请求的Route对应的GatewayFilterChain。

在网关处进行过滤处理。


API网关:SpringCloud Gateway

1,适配器模式,以适配GlobalFilter

2,判断是否实现Ordered接口

3,实现了Ordered接口,返回的是OrderedGatewayFilter对象



globalFilter是Gateway的全局过滤器。


通过传入全局过滤器,对这些过滤器进行适配处理。过滤器有优先级。如果实现了Ordered接口,返回的是OrderedGatewayFilter对象。否则的话,返回过滤器的适配器,来适配GlobalFilter。


FilteringWebHandler的handler方法首先获得对应的路由的过滤器和全局过滤器。


API网关:SpringCloud Gateway

1,加入全局过滤器

2,过滤器排序

3,按照优先级,对该请求进行过滤


AnnotationAwareOrderComparator是OrderComparator的子类。按照优先级,生成过滤器链,对请求进行过滤处理。这里的过滤器链通过内部类静态类DefaultGatewayFilterChain实现,该类的话实现了GatewayFilterChain接口,用于按优先级过滤。


API网关:SpringCloud Gateway



路由定义定位器


RouteDefinitionLocator是路由定义定位器的顶级接口。

API网关:SpringCloud Gateway

可以看到getRouteDefinition方法。来获取路由的定义。RouteDefinition对象为属性定义在GatewayProperties中,网关服务启动时读取的配置文件中的配置。


API网关:SpringCloud Gateway



通过RouteDefinitionLocator的类图,有四个实现类:


API网关:SpringCloud Gateway

PropertiesRouteDefinitionLocator:基于属性配置的

DiscoveryClientRouteDefinitionLocator:基于服务发现的

CompositeRouteDefinitionLocator:组合方式

CachingRouteDefinitionLocator:缓存方式


还有一个接口RouteDefintionRepository,用于对路由定义进行操作,用来保存和删除路由定义。





路由定义的数据访问操作


RouteDefinitionRepository接口中的方法对RouteDefinition进行增删查操作。


API网关:SpringCloud Gateway


API网关:SpringCloud Gateway


RouteDefinitionWriter对路由定义进行操作。


API网关:SpringCloud Gateway


InMemoryRouteDefinitionRepository实现了RouteDefinitionRepository接口,基于内存的路由定义仓库。


基于属性配置的RouteDefinitionLocator基于属性配置的路由定义定位器是PropertiesRouteDefinitionLocator,从配置文件读取路由配置。


通过构造函数传入GatewayProperties对象,读取其中的路由配置信息。


API网关:SpringCloud Gateway

增加了默认的过滤器defalut-filters和一条路由配置。


基于服务发现的RouteDefinitionLocator


DiscoveryClientRouteDefinitionLocator该类通过服务发现组件获取注册中心的服务信息。应避免spring-boot-strater-web的依赖,避免和SpringCloudGateway依赖的WebFlux冲突。


API网关:SpringCloud Gateway


在DiscoveryLocatorProperties中定义了属性,enabled开始服务发现,routeIdPrefix路由的前缀,includeExpression网关是否集成一个服务。urlExpression为每个路由创建uri。PredicateDefintion路由定义,FilterDefition过滤器定义。


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

1,对includeExpression和urlExpression表达式处理

2,根据includeExpression表达式,过滤不符合ServiceInstance

API网关:SpringCloud Gateway

4,增加配置的断言表达式

5,增加配置中的过滤器


缓存方式与组合方式的RouteDefinitionLocator


缓存方式的路由定义定位器CachingRouteDefinitionLocator,缓存到本地,当需要缓存更新时,可以通过路由刷新事件RefreshRoutesEvent,将本地的缓存清空,通过代理RouteDefinitionLocator重新请求路由定义信息。



路由定位器


直接获取路由的方法是通过RouteLocator接口获取。


API网关:SpringCloud Gateway


API网关:SpringCloud Gateway


通过RouteLocator的类图,通过RouteLocator有三个实现类。


基于路由定义方式的RouteLocator


通过RouteDefinitionRouteLocator获取RouteDefinition,将路由定义转换成Route。RouteDefinitionRouteLocator在实例化进行初始化的过程,对路由断言和过滤器进行初始化。


API网关:SpringCloud Gateway

1,设置routeDefinitionLocator

2,初始化路由断言

3,初始化网关过滤器


API网关:SpringCloud Gateway


获取路由的方法,基于传入的具体RouteDefinitionLocator获取路由定义


API网关:SpringCloud Gateway

获得具体的RouteDefinitionLocator获取路由定义,map方法将每个RouteDefinition转换成Route


API网关:SpringCloud Gateway


RouteDefinitionLocator的convertToRoute是具体的转换方法,在该方法中,涉及路由断言和网关过滤器的处理,返回构建为Route对象。



路由断言


使用RoutePredicateFactory创建Predicate对象。Predicate对象可以赋值给Route,路由断言可以用于匹配请求对应的Route。


API网关:SpringCloud Gateway

返回apply的实现,返回AsyncPredicate。该接口继承ShortcutConfigurable接口,该接口有多种实现,传入RouteDefinitionLocator获取路由定义。断言的种类很多。不同断言配置的参数不一样,每种断言和过滤器的实现会实现ShortConfigurable接口,指定自身参数个数和顺序。



Datetime类型的断言工厂


AfterRoutePredicateFactory:接收一个日期是配置时间之后

BeforeRoutePredicateFactory:接收一个日期是配置时间之前

BetweenRoutePredicateFactory:接收两个参数之间



AfterRoutePredicateFactory:


API网关:SpringCloud Gateway

请求的时间必须晚于上海时间2018年3月20号10:42




RemoteAddrRoutePredicateFactory属于根据请求Ip进行路由决策。IP/子网掩码


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway


API网关:SpringCloud Gateway




API网关:SpringCloud Gateway


遍历配置文件中指定的RemoteAddr数组。addSource方法如下。


API网关:SpringCloud Gateway

1,当RemoteAddr没有子网掩码时候,默认为/32,根据ip和子网,确定RemoteAddr的范围,加入到sources中。




路由权重


Gateway 提供了基于路由权重的断言工厂,WeightRoutePredicateFactory同时实现了权重的功能,按照权重选择同一个分组中的路由。


API网关:SpringCloud Gateway

/weight/** , 路由转发的路由定义。这两个路由属于同一个权重分组,weight_route1的权重为1,weight_route2的权重为9。10个访问/weight/**路径请求来说,9个路由到weight_route2,1个路由到weight_route1。




基于Cookie的断言工厂


CookieRoutePredicateFactory是Cookie类型的路由断言工厂。给定名称的值与正则式匹配的cookie。


如果请求的cookie名为chocolate,其值与正则式表达式ch.p相匹配,该请求与该路由匹配。


API网关:SpringCloud Gateway


基于头部的断言工厂


HeaderRoutePredicateFactory是头部类型的路由断言工厂。头部有X-Request-Id,并且该头部值匹配\d+正则表达式。




API网关:SpringCloud Gateway



基于请求方法的断言工厂


MethodRoutePredicateFactory是请求类型的路由断言工厂。接收http请求方法作为参数。


API网关:SpringCloud Gateway



基于请求路径的断言工厂


PathRoutePredicateFactory基于请求路径的路由断言工厂。


API网关:SpringCloud Gateway

请求路径是/foo/l,或者/foo/bar,就会匹配该路由。



基于请求参数的断言工厂


接收两个参数:一个必须的请求param和一个可选的正则表达式。


API网关:SpringCloud Gateway

请求中包含baz参数,它的值匹配ba.正则表达式。



网关过滤器


GatewayFilter网关过滤器用于拦截和链式处理web请求。


API网关:SpringCloud Gateway



API网关:SpringCloud Gateway


接口中定义了方法filter,GatewayFilter有三个实现类。ModifyResponseGatewayFilter用于修改响应体,OrderdGatewayFiltre是一个有序的网关过滤器。GatewayFilterAdapter是一个适配器类。


有序的GatewayFilter和GatewayFilterAdapter


大家都知道过滤器是有优先级的,因此的话。有序的网关过滤器实现了Ordered接口,具体的过滤器功能,只需要调用代理的过滤器。


GatewayFilterAdapter用于网关过滤器的适配。在网关过滤器链GatewayFilterChain中应用GatewayFilter过滤请求。GatewayFilterAdapter将全局过滤器GlobalFilter适配成GatewayFilter。



GatewayFilterFactory内部类


API网关:SpringCloud Gateway


路由过滤器修改传入的http请求或者传入的response响应。apply用于定义具体的过滤操作。泛型  C 是各个实现类中的配置。


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

AbstractChangeRequestUriGatewayFilterFactory:通过方法determineRequestUri实现改变URI的逻辑。另一个抽象类AbstractNameValueGatewayFilterFactory:给键值对参数类型的网关过滤器。或者AddResponseHeader。



有多种过滤器,包括头部过滤器,路径类过滤器,Hystrix过滤器,变更请求url,参数和状态码的过滤器等等。



头部过滤器


AddRequestHeaderGatewayFilterFactory:增加请求的头部信息

AddResponseHeaderGatewayFilterFactory:增加响应头部

RemoveRequestHeaderGatewayFilterFactory:在请求发送到下游之前,请求移除设置的头部信息

RemoveResponseHeaderGatewayFilterFactory:在返回结果回客户端之前,移除设置的响应头部信息。

setRequestHeaderGatewayFilterFactory:请求经过网关转发时候,过滤器回用给定的名字替换所有的头部

setResponseHeaderGatewayFilterFactory:替换头部


API网关:SpringCloud Gateway

增加X-Response-Foo:Bar头部。



路径过滤器



API网关:SpringCloud Gateway

一个匹配请求路径为/foo/bar,在构造函数发送到下游的请求之前,setpath_route修改请求路径/bar。



StripPrefixGatewayFilterFactory: 该参数指明在发送到下游之前,移除路径分段的数量。


API网关:SpringCloud Gateway

请求/user/bar/foo,通过网关请求user-service时候,最终请求路径将会变成http://127.16.1.100:8080/foo。



Hystrix过滤器



API网关:SpringCloud Gateway

用一个HystrixCommand名为fallbackcmd包装过滤器,如果服务被降级,该请求就会转发到该url对应的控制器。


API网关:SpringCloud Gateway

1,设置commandKey,使用配置文件中的name属性

2,设置setter,HystrixObservableCommand构造器流接口,组成为commandKey和groupKey。

3,构造HystrixObservalbleCommand传入过滤器链,具体请求,fallbackUri。


通过HystrixObservableCommand的construct方法,获得过滤器执行的Observable


Hystrix过滤器接收配置文件中的HystrixCommand,还有一个可选的fallbackUri参数。



变更请求URL的过滤器


对于符合要求的请求。应用RequestHeaderToRequestUri过滤器。在路由断言中增加头部的判断,确保头部存在请求中,符合头部的应用正则表达式,将会用头部X-Next-Url值作为新的转发url。


API网关:SpringCloud Gateway


其他过滤器


RequestRateLimiterGatewayFilterFactory:属于限流类型的过滤器。接收三个参数,令牌桶上限,平均填充速度和关键字Bean名称。当一个请求来临时,拿走一个令牌,没有令牌了就阻塞或者拒绝服务。


RetryGatewayFilterFactory:重试过滤器,转发到代理服务时候,遇到指定的服务端错误。比如说httpStatus为500,设定请求重试的次数。


RedirectToGatewayFilterFactory:转发类型过滤器。接收状态码和一个url。


API网关:SpringCloud Gateway

头部Location:http://acme.org,状态码302


SaveSessionGatewayFilterFactory:会话类型过滤器

API网关:SpringCloud Gateway

在Spring Session MongoDB,这种惰性数据存储的时候,确保转发之前会话的数据已经被存储。



全局过滤器


GlobalFilter有十个实现类,路由转发,负载均衡,ws路由,Netty路由等。


转发路由过滤器


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

1,获取请求的uri的格式

2,该请求未被路由处理或者uri的格式是“forward”

3,进行DispatcherHandler处理


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

在ServerWebExchangeUtil中,返回请求属性的可变映射



负载均衡客户端过滤器


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

1,保存原始的url

2,负载均衡到具体的服务实例

3,没有提供前缀,使用默认的

4,根据获取的服务实例信息,重新弄组装请求url


API网关:SpringCloud Gateway

负载均衡客户端过滤器实现:


构造函数传入负载均衡客户端,获取请求的URL及其前缀,如果URL不为空并且前缀为lb或者网关请求的前缀是lb,保存原始的url,负载到具体的服务实例并且获取服务实例信息,重新组装请求的url。添加请求url到GATEWAY_REQUEST_URL_ATTR,提交过滤器链进行过滤。



基于Netty路由和响应过滤器


如果GATEWAY.REQUEST_URL_ATTR的URL具有http或者https前缀,Netty路由过滤器将执行。使用httpClient进行下游代理请求。响应放在CLIENT_RESPOSNSE_ATTR请求属性,在过滤器链中传递。


API网关:SpringCloud Gateway

API网关:SpringCloud Gateway

NettyRoutingFilter过滤器构造函数有两个参数,一个是HttpClient,通过该属性请求后端的http服务。另外一个是ObjectProvider类型的headersFilters用于头部过滤。



API网关:SpringCloud Gateway

判断前缀是不是http或者https,如果请求已经被路由或者前缀不合法,调用过滤器链直接向后传递。


API网关:SpringCloud Gateway


filterRequest用于对请求的头部信息进行处理,定义在接口HttpHeadersFilter默认方法。


有三个实现类:



XForwardedHeadersFilter:增加X-Forwarded-For,X-Forwarded-Host,X-Forwarded-Port,X-Forwarded-Proto头部。


在CLIENT_RESPONSE_ATTR请求属性中是否存在Netty,HttpClientResponse,有则会用NettyWriteResponseFilter。



路由到指定请求URL过滤器


ServerWebExchangeUtils,GATEWAY_ROUTE_ATTR请求属性中有Route对象,就会运行RouteToRequestUrlFilter过滤器。根据请求URI创建一个新的URI,对Route对象的URI属性进行更新。新的URI位于ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR属性,继续向后传递到路由转发的过滤器。


1,获取请求的Route,如果为空,直接提交过滤链

2,否则的话,获取routeUri,判断routeUri是否特殊。如果是的话需要处理url,保存前缀到GATEWAY_SCHEME_PREFIX_ATTR,将routeUri替换为schemeSpecificPart;最后拼接requestUrl,转化为定义的routeUri。最后提交到过滤器链。


Websocket路由过滤器


请求中的ServerWebExchangeUtil.GATEWAY_REQUEST_URL_ATTR属性对应URL前缀为ws或者wss。使用websocket过滤器。最后将请求通过代理转发。



API端点


Gateway提供了内置端点,如过滤器列表,路由列表,单个路由信息。网关服务可以看到内置端点。


/actuator/gateway/routes/{id},methods=[DELETE]

代表删除单个路由

/actuator/gateway/routes/{id},methods=[POST]
代表增加单个路由

/actuator/gateway/routes/{id},methods=[GET]

查看单个路由

/actuator/gateway/routes,methods=[GET]

获取路由列表

/actuator/gateway/refresh,methods=[POST]

路由刷新

/actuator/gateway/globalfilters,methods=[POST]

获得全局过滤器列表

/actuator/gateway/routefilters,methods=[GET]

路由过滤器工厂列表

/actuator/gateway/routes/{id}/combinedfilters,methods=[GET]

单个路由的联合过滤器




以上是关于API网关:SpringCloud Gateway的主要内容,如果未能解决你的问题,请参考以下文章

API网关:SpringCloud Gateway

api-gateway实践(13)新服务网关 - SpringCloud Zuul

SpringCloud Hoxton——Gateway服务网关

SpringCloud Hoxton——Gateway服务网关

springcloud—— 网关服务Gateway

springcloud—— 网关服务Gateway